Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python模拟方法调用参数显示列表的最后状态_Python_Unit Testing_Mocking - Fatal编程技术网

Python模拟方法调用参数显示列表的最后状态

Python模拟方法调用参数显示列表的最后状态,python,unit-testing,mocking,Python,Unit Testing,Mocking,我有一个以列表为参数的函数。该函数被多次调用,并且每次更新某些列表值时都会调用。我用来捕获调用参数的mock对象总是在列表中显示所有调用参数的最新值。下面的代码显示了该问题 from mock import MagicMock def multiple_calls_test(): m = MagicMock() params = [0, 'some_fixed_value', 'some_fixed_value'] for i in xrange(1,10):

我有一个以列表为参数的函数。该函数被多次调用,并且每次更新某些列表值时都会调用。我用来捕获调用参数的mock对象总是在列表中显示所有调用参数的最新值。下面的代码显示了该问题

from mock import MagicMock

def multiple_calls_test():
    m = MagicMock()
    params = [0, 'some_fixed_value', 'some_fixed_value']
    for i in xrange(1,10):
        params[0] = i
        m(params)
    for args in m.call_args_list:
        print args[0][0]

multiple_calls_test()
这里是输出,注意所有调用的第一个列表元素都是9

[9, 'some_fixed_value', 'some_fixed_value']
[9, 'some_fixed_value', 'some_fixed_value']
[9, 'some_fixed_value', 'some_fixed_value']
[9, 'some_fixed_value', 'some_fixed_value']
[9, 'some_fixed_value', 'some_fixed_value']
[9, 'some_fixed_value', 'some_fixed_value']
[9, 'some_fixed_value', 'some_fixed_value']
[9, 'some_fixed_value', 'some_fixed_value']
[9, 'some_fixed_value', 'some_fixed_value']

有没有办法强迫mock对象复制list参数,而不是保存对实际list的引用?或者用其他方法为每个方法执行断言正确的值?谢谢。

不幸的是,这似乎是
mock
库的一个缺点,从代码来看,如果不修补mock库本身,这是不可能的。但是,似乎有一种相当轻量级的方法可以达到您想要的效果:

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)
然后(为了说明明显的问题),只需将
MagicMock
替换为
CopyArgsMagicMock
,您就会看到所需的行为


请注意,这只针对提供的用例进行了测试,因此这可能不是解决问题的完整而健壮的解决方案,但希望它能被证明是有用的。

尝试m.mock_调用。这将列出所有拨打的电话。我认为这应该奏效:

>>> from unittest.mock import MagicMock, call
>>> m = MagicMock()
>>> m('abc')
<MagicMock name='mock()' id='2634881401576'>
>>> m('def')
<MagicMock name='mock()' id='2634881401576'>
>>> call('abc') in m.mock_calls
True
>>> call('ghi') in m.mock_calls
False
>从unittest.mock导入MagicMock,调用
>>>m=MagicMock()
>>>m(‘abc’)
>>>m('def'))
>>>m.mock_调用中的调用('abc')
真的
>>>m.mock_调用中的调用('ghi')
假的

对于Python3.8,已接受的解决方案不再适用于我。
但是,官方python文档中有一个解决方案:

您必须向下滚动一点才能找到以下内容:

另一种方法是创建Mock或MagicMock的子类来复制(使用copy.deepcopy())参数。下面是一个示例实现:


这对我的python 3.8很有用。

谢谢。这确实有帮助。我只是想指出,调用方需要从Super()返回值才能从Mock获取返回值。@robjohncox,示例的最后一行应该使用
\u Mock\u self
作为
Super
的第二个参数,而不是
self
。谢谢。它确实有用!
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)