I have the following class, and I would like to write several unit tests for it:
class JsonSchemaValidator:
def __init__(self, json_file):
self.json_file = json_file
self.schema = json.load(open(json_file))
def check_json_schema(self):
print(self.json_file)
Draft3Validator.check_schema(self.schema)
As shown above, the class has two instances of self.json_file
and self.schema
, and I would like to define the schema per test. How can I set up the tests, so schema can be defined per test case?
class TestValidator(TestCase):
def test_check_json_schema1(self):
schema = {
"type": "object",
"properties": {
"key1": {"type": "string"}
},
}
actual = JsonSchemaValidator.check_json_schema() ##??
self.assertIsNone(actual)
def test_check_json_schema2(self):
schema = {
"type": "object",
"properties": {
"key2": {"type": "SOME_TYPE"}
},
}
self.assertRaises(SchemaError, JsonSchemaValidator.check_json_schema, schema) ##??
The problem is that you don't want your code to actually open
a file on the disk and load
it, you want to simply provide the result.
One way to do that is to mock the open
and json.load
references that TestValidator
uses, like that :
import json
import unittest
import unittest.mock as mocking
class JsonSchemaValidator:
def __init__(self, json_file_path):
self.json_file_path = json_file_path
self.schema = json.load(open(json_file_path))
def check(self):
print(self.json_file_path)
# do the validation here
class TestValidator(unittest.TestCase):
def test_check_json_schema1(self):
schema = {
"type": "object",
"properties": {
"key1": {"type": "string"}
},
}
with mocking.patch("builtins.open"), \
mocking.patch.object(json, "load", new=mocking.Mock(return_value=schema)):
validator = JsonSchemaValidator("/blah")
print(validator.schema) # exactly what we wanted : {'type': 'object', 'properties': {'key1': {'type': 'string'}}}
# do your test here
validator.check()
...
You can check by adding print(json.load, open)
to JsonSchemaValidator.__init__
, you will get something like :
<Mock id='139724038827840'> <MagicMock name='open' id='139724039146992'>
because they have been mocked while you were in the context manager (with
).
(I renamed json_file
to json_file_path
because I think it makes things more clear)