为什么mock会在调用时忽略传递给模拟方法的实例/对象?

时间:2015-09-06 01:51:20

标签: python unit-testing mocking

我最近注意到,如果我使用mock.patch模拟一个方法,它就不会列出传递给call_args字段中的模拟方法的实例对象。这是设计的吗?下面的代码/输出可能更好地解释我的意思:

#!/usr/bin/env python2

from mock import patch

class Dog(object):
    def bark(self):
        print("Woof woof!")

Dog().bark()

def new_method(*args):
    print("args = %s" % str(args))

Dog.bark = new_method

Dog().bark()

with patch.object(Dog, "bark"):
    d = Dog()
    d.bark()
    print("d.bark was called: %s" % str(d.bark.called))
    print("d.bark was called with args/kwargs: %s" % str(d.bark.call_args))

输出是:

Woof woof!
args = (<__main__.Dog object at 0x7f42c2dbc3d0>,)

# Mocking bit
d.bark was called: True
d.bark was called with args/kwargs: ((), {})

您可以看到实例对象在替换new_method时传递给bark。但是你无法在模拟方法的call_args中看到它。这不奇怪吗?我正在使用python模拟库的1.01版本。

1 个答案:

答案 0 :(得分:7)

通过

with patch.object(Dog, "bark"):

您正在修补Dog.bark方法的静态实例,因为您正在修补Dog类,而不是Dog对象。

现在,mock方法将被调用为静态方法而不是对象方法:这意味着self属性不会被传递。

如果要创建具有与原始方法相同签名的补丁,可以使用autospec=True属性:在这种情况下,mock方法将是对象方法而不是静态方法。

>>> from mock import patch
>>> with patch.object(Dog, "bark", autospec=True):
...     d = Dog()
...     d.bark()
...     print("d.bark was called with args/kwargs: %s" % str(d.bark.call_args))
... 
<MagicMock name='bark()' id='139848306278672'>
d.bark was called with args/kwargs: call(<Dog object at 0x7f30f89ef390>)