【问题标题】:python patch with side_effect on Object's method is not called with self不使用 self 调用对 Object 的方法具有副作用的 python 补丁
【发布时间】:2016-09-09 14:54:45
【问题描述】:

我在 patch.object 中遇到了一个令人惊讶的 side_effect 参数行为,其中替换原始的函数没有收到 self

class Animal():
    def __init__(self):
        self.noise = 'Woof'

    def make_noise(self):
        return self.noise

def loud(self):
    return self.noise.upper() + '!!'


from unittest.mock import patch

dog = Animal()
dog.make_noise()
with patch.object(Animal, 'make_noise', side_effect=loud):
    dog.make_noise()

这个给:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/lustre/home/production/Applications/python/python-3.4.4/lib/python3.4/unittest/mock.py", line 902, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/lustre/home/production/Applications/python/python-3.4.4/lib/python3.4/unittest/mock.py", line 968, in _mock_call
    ret_val = effect(*args, **kwargs)
TypeError: loud() missing 1 required positional argument: 'self'

如果我将loud 函数更改为

def loud(*args, **kwargs):
    print(args)
    print(kwargs)

我得到以下输出:

()
{}

有没有办法从一个对象中替换一个函数并仍然接收自我?

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    self 仅提供给绑定方法(因为函数是descriptors)。 Mock对象不是这样的方法,side_effect函数没有绑定,所以self确实不会传入。

    如果您必须可以访问side_effect 对象中的实例,则必须使用实际函数修补类上的函数:

    with patch.object(Animal, 'make_noise', new=loud):
    

    现在make_noiseloud 类上的loud 函数替换,所以它会被绑定:

    >>> with patch.object(Animal, 'make_noise', new=loud):
    ...     dog.make_noise()
    ...
    'WOOF!!'
    

    另一种方法是设置autospec=True,此时mock将使用真实函数模拟出make_noise()

    >>> with patch.object(Animal, 'make_noise', autospec=True, side_effect=loud):
    ...     dog.make_noise()
    ...
    'WOOF!!'
    

    另请参阅模拟入门部分中的Mocking Unbound Methods section

    【讨论】:

    • 这里有一个重要注意事项,new 不是模拟函数,因此它缺少调用拦截的细节(调用计数、调用参数等)。如果您需要获取这些,请使用此处最后描述的解决方案 - autospec + 副作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-11
    • 2019-11-11
    • 2013-11-08
    • 1970-01-01
    相关资源
    最近更新 更多