How can i check call arguments if they will change with unittest.mock

mocking, python

Solution

There is a chapter "Coping with mutable arguments" in the documentation, which suggests several solutions to your problem.

I'd go with this one:

>>> from copy import deepcopy
>>> class CopyingMock(MagicMock):
...     def __call__(self, *args, **kwargs):
...         args = deepcopy(args)
...         kwargs = deepcopy(kwargs)
...         return super(CopyingMock, self).__call__(*args, **kwargs)
...
>>> c = CopyingMock(return_value=None)
>>> arg = set()
>>> c(arg)
>>> arg.add(1)
>>> c.assert_called_with(set())
>>> c.assert_called_with(arg)
Traceback (most recent call last):
    ...
AssertionError: Expected call: mock(set([1]))
Actual call: mock(set([]))
>>> c.foo
<CopyingMock name='mock.foo' id='...'>

Problem

One of my classes accumulates values in a list, uses the list as an argument to a method on another object and deletes some of the values in this list. Something like ``` element = element_source.get() self.elements.append(element) element_destination.send(elements) self.remove_outdated_elements() ``` But when when i was trying to test this behavior, i've found that mocks don't copy their arguments. ``` >>> from unittest.mock import Mock >>> m = Mock() >>> a = [1] >>> m(a) <Mock name='mock()' id='139717658759824'> >>> m.call_args call([1]) >>> a.pop() 1 >>> m.assert_called_once_with([1]) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.3/unittest/mock.py", line 737, in assert_called_once_with return self.assert_called_with(*args, **kwargs) File "/usr/lib/python3.3/unittest/mock.py", line 726, in assert_called_with raise AssertionError(msg) AssertionError: Expected call: mock([1]) Actual call: mock([]) ``` Is there a way to make Mock copy it's call arguments? If not, what is the best way to test this kind of behavior?

Original source