Reputation: 2427
Writing some unit tests in python and using MagicMock to mock out a method that accepts a JSON string as input. In my unit test, I want to assert that it is called with given arguments, however I run into issues with the assert statement, since the ordering of objects within the dict doesn't matter, besides in the assert statement for the string. Simplified example of what I am trying to achieve below.
mock_funct = MagicMock()
# mocked function called elsewhere
expected = {"a":"a", "b":"b"}
mock_funct.assert_called_once_with(json.dumps(expected))
The above may pass or may fail due to the arbitrary ordering of the keys within the dict when it is dumped to json, ie both '{"a":"a", "b":"b"}'
and '{"b":"b", "a":"a"}'
are valid dumps but one would fail and one would pass, however I would like to write the test so that either would pass.
Upvotes: 8
Views: 3944
Reputation: 9459
Under the hood unittest's assert_called_once_with
will perform equality checks on each argument in the call.
Python has a dunder method for controlling how equality checking is performed: __eq__
Knowing this we can create a wrapper class to help us:
import json
class JsonChecker:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return json.loads(other) == self.value
mock_funct.assert_called_once_with(JsonChecker(expected))
Upvotes: 0
Reputation: 310287
Unfortunately, you'll need to do your own checking here. You can get the calls from the mock via it's call_args_list
attribute (or, simply call_args
in this case since you have already asserted that it is called only once). I'll assume you're using unittest
in my example code -- but it should be easy enough to adapt for any testing framework ...
mock_funct.assert_called_once_with(mock.ANY)
call = mock_funct.call_args
call_args, call_kwargs = call # calls are 2-tuples of (positional_args, keyword_args)
self.assertEqual(json.loads(call_args[0]), expected)
I've still used assert_called_once_with
to make sure that the function was only called once with a single positional argument, but then I open up the call to look at that argument to check that it is correct.
Upvotes: 15