I am trying to unit test a custom exception called TargetException
.
One of the arguments to this exception is itself an exception.
Here's the relevant part of my test:
mock_exception.assert_called_once_with(
id,
AttributeError('invalidAttribute',)
)
Here's the test failure message:
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 948, in assert_called_once_with
return self.assert_called_with(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 937, in assert_called_with
six.raise_from(AssertionError(_error_message(cause)), cause)
File "/usr/local/lib/python2.7/site-packages/six.py", line 718, in raise_from
raise value
AssertionError: Expected call: TargetException(<testrow.TestRow object at 0x7fa2611e7050>, AttributeError('invalidAttribute',))
Actual call: TargetException(<testrow.TestRow object at 0x7fa2611e7050>, AttributeError('invalidAttribute',))
In both the "Expected call" and the "Action call," the same arguments are present -- at least it appears that way to me.
Do I need to pass the AttributeError a different way to resolve the error?
The problem is that you compare the instances of the contained exception. As the AttributeError
instance created in the tested function and the instance used for comparison in test are different, the assertion fails.
What you could do instead is testing the called arguments separately to ensure they are of the correct type:
@mock.patch('yourmodule.TargetException')
def test_exception(mock_exception):
# call the tested function
...
mock_exception.assert_called_once()
assert len(mock_exception.call_args[0]) == 2 # shall be called with 2 positional args
arg1 = mock_exception.call_args[0][0] # first argument
assert isinstance(arg1, testrow.TestRow) # type of the first arg
... # more tests for arg1
arg2 = mock_exception.call_args[0][1] # second argument
assert isinstance(arg2, AttributeError) # type of the second arg
assert str(arg2) == 'invalidAttribute' # string value of the AttributeError
E.g. you test for the class and for the relevant values of the arguments separately. Using assert_called_with
works only for PODs, or if you already know the called instance (for example if it is a singleton, or a known mock).