【问题标题】:Why does mock ignore the instance/object passed to a mocked out method when it is called?为什么模拟在调用时忽略传递给模拟方法的实例/对象?
【发布时间】:2015-09-06 01:51:20
【问题描述】:

我最近注意到,如果我使用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: ((), {})

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

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

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

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

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

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

    >>> 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>)
    

    【讨论】:

    • 谢谢 Michele,这回答了我的问题!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    • 2017-10-31
    相关资源
    最近更新 更多