Python mock method call arguments display the last state of a list

Unfortunately, this looks to be a shortcoming of the mock library, and from looking at the code this doesn't look to be possible without patching the mock library itself. However, it looks like there is a fairly lightweight way to do this to get the effect you are looking for:

import copy
from mock import MagicMock


class CopyArgsMagicMock(MagicMock):
    """
    Overrides MagicMock so that we store copies of arguments passed into calls to the
    mock object, instead of storing references to the original argument objects.
    """

    def _mock_call(_mock_self, *args, **kwargs):
        args_copy = copy.deepcopy(args)
        kwargs_copy = copy.deepcopy(kwargs)
        return super(CopyArgsMagicMock, self)._mock_call(*args_copy, **kwargs_copy)

Then (to state the obvious) simply replace your MagicMock with a CopyArgsMagicMock and you should see the required behavior.

Please note that this has only been tested for the use case provided, so this may not be a complete and robust solution to the problem, but hopefully it proves useful.


For python 3.8 the accepted solution did not work anymore for me.
However, there is a solution in the official python docs:
https://docs.python.org/3/library/unittest.mock-examples.html#coping-with-mutable-arguments
You have to scroll down a bit to find the following:

An alternative approach is to create a subclass of Mock or MagicMock that copies (using copy.deepcopy()) the arguments. Here’s an example implementation:

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)

This worked for me for python 3.8.