Reputation: 2070
I am new to python testing. I am using pytest and started learning about mocks and patches. I am trying to write a test case for one of my methods.
helper.py
def validate_json_specifications(path_to_data_folder, json_file_path, json_data) -> None:
""" Validates the json data with a schema file.
:param path_to_data_folder: Path to the root folder where all the JSON & schema files are located.
:param json_file_path: Path to the json file
:param json_data: Contents of the json file
:return: None
"""
schema_file_path = os.path.join(path_to_data_folder, "schema", os.path.basename(json_file_path))
resolver = RefResolver('file://' + schema_file_path, None)
with open(schema_file_path) as schema_data:
try:
Draft4Validator(json.load(schema_data), resolver=resolver).validate(json_data)
except ValidationError as e:
print('ValidationError: Failed to validate {}: {}'.format(os.path.basename(json_file_path), str(e)))
exit()
Things I want to test are:
json_data
?ValidationError
thrown and exit is called?Here is my attempt at writing a test case so far. I decided to patch open
method & Draft4Validator
class.
@patch('builtins.open', mock_open(read_data={}))
@patch('myproject.common.helper.jsonschema', Draft4Validator())
def test_validate_json_specifications(mock_file_open, draft_4_validator_mock):
validate_json_specifications('foo_path_to_data', 'foo_json_file_path', {})
mock_file_open.assert_called_with('foo_path_to_data/schema/foo_json_file_path')
draft_4_validator_mock.assert_called()
I wanted to pass some fake data and paths to my method instead of trying to pass real data. I got this error message
UPDATE:
@patch('myproject.common.helper.jsonschema', Draft4Validator())
E TypeError: __init__() missing 1 required positional argument: 'schema'
How do I go about creating patches for 2 methods specially Draft4Validator
and how do I simulate ValidationError
exception?
Upvotes: 1
Views: 2437
Reputation: 2700
You were patching the Draft4Validator
wrong. Basically what you were doing is creating a new Draft4Validator object without the required arguments and assigning it to the myproject.common.helper.jsonschema
call everytime (had you created it with the required arguments).
Read more about it here: https://docs.python.org/3/library/unittest.mock-examples.html#patch-decorators
For checking assertions about expected exceptions check: http://doc.pytest.org/en/latest/assert.html#assertions-about-expected-exceptions
I guess by your question and requirements that you want something along the lines of this:
@patch('sys.exit')
@patch('myproject.common.helper.jsonschema.Draft4Validator')
@patch('builtins.open')
def test_validate_json_specifications(mock_file_open, draft_4_validator_mock, exit_mock):
with pytest.raises(ValidationError):
mock_file_open.return_value = {}
draft_4_validator_mock = Mock()
draft_4_validator_mock.side_effect = ValidationError
validate_json_specifications('foo_path_to_data', 'foo_json_file_path', {})
assert draft_4_validator_mock.call_count == 1
assert draft_4_validator_mock.validate.assert_called_with({})
assert exit_mock.call_count == 1
Upvotes: 2