How can i check call arguments if they will change with unittest.mock
Question: 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?


Answer: There is a chapter "[Coping with mutable
arguments](http://docs.python.org/dev/library/unittest.mock-
examples.html#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='...'>
    

