問題描述
我的一個類在一個列表中累積值,將該列表用作另一個對象的方法的參數,并刪除該列表中的一些值.類似的東西
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()
但是當我嘗試測試這種行為時,我發(fā)現模擬不會復制他們的論點.
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([])
有沒有辦法讓 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?
推薦答案
有個章節(jié)Coping with mutable arguments" 在文檔中,它為您的問題提出了幾種解決方案.
There is a chapter "Coping with mutable arguments" in the documentation, which suggests several solutions to your problem.
我會選擇這個:
>>> 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='...'>
這篇關于我如何檢查調用參數是否會隨 unittest.mock 改變的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!