Python mock:包装实例方法 [英] Python mock: wrap instance method

查看:47
本文介绍了Python mock:包装实例方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要什么:确保在 with 语句中创建的所有 Foo 实例都通过 wraps=Foo 将它们的 foo 实例方法包装在 MagicMock 中.foo.我想要这个的原因是我可以在方法 foo 上跟踪 call_count 为所有创建的 Foo 实例.现在我这么说似乎有点不可能......

<预><代码>>>>从模拟导入补丁......类Foo(对象):...... def foo(self):...返回foo"...... 使用 patch("__main__.Foo.foo", wraps=Foo.foo) 作为 m:... foo = foo()...打印(foo.foo())回溯(最近一次调用最后一次):文件a.py",第 12 行,在 <module> 中打印(foo.foo())文件/disk/software/lib/python27/mock/mock.py",第 1062 行,在 __call__ 中返回 _mock_self._mock_call(*args, **kwargs)_mock_call 中的文件/disk/software/lib/python27/mock/mock.py",第 1132 行返回 self._mock_wraps(*args, **kwargs)类型错误:必须使用 Foo 实例作为第一个参数调用未绑定的方法 foo()(什么都没有)

问题模拟的 foo 方法未绑定到通过 foo = Foo() 创建的 foo 实例,因为它包装了未绑定的方法 Foo.foo.有谁知道如何确保模拟方法绑定到实例?

我已经知道的:

<预><代码>>>>foo = foo()... 使用 patch.object(foo, "foo", wraps=foo.foo) 作为 m:...打印(foo.foo())富"

但这并不能满足我的约束,即对象必须在 patch 上下文中实例化.

解决方案

我上面提出的和不正确的解决方案的问题

with patch("__main__.Foo.foo", wraps=Foo.foo) as m:...

Foo 上的 foo 方法被模拟,使得它包装了未绑定的方法 Foo.foo,这自然不起作用,因为未绑定的方法 Foo.foo 不知道稍后调用时它附加到哪个实例.

我能想到的最简单的解决方案

来自模拟导入补丁,MagicMockFoo类:def foo(self):返回foo"类 MockFoo(Foo):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)# MockFoo 的每个实例现在都有它的 `foo` 方法# 包裹在一个 MagicMock 中self.foo = MagicMock(wraps=self.foo)使用 patch("__main__.Foo", MockFoo) 作为 m:foo = foo()打印(foo.foo())断言 foo.foo.call_count == 1

What I would like: Ensure that all instances of Foo that are created inside the with statement have their foo instance method wrapped in a MagicMock via wraps=Foo.foo. The reason I want this is so that I can track call_count on the method foo for all instances of Foo that are created. Now that I say it like that it seems kind of impossible...

>>> from mock import patch
...
... class Foo(object):
...
...     def foo(self):
...         return "foo"
...
... with patch("__main__.Foo.foo", wraps=Foo.foo) as m:
...     foo = Foo()
...     print(foo.foo())

Traceback (most recent call last):
  File "a.py", line 12, in <module>
    print(foo.foo())
  File "/disk/software/lib/python27/mock/mock.py", line 1062, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/disk/software/lib/python27/mock/mock.py", line 1132, in _mock_call
    return self._mock_wraps(*args, **kwargs)
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)

The problem The mocked foo method isn't bound to the foo instance created via foo = Foo() because it's wrapping the unbound method Foo.foo. Does anyone know how to ensure that the mocked method is bound to an instance?

What I already know:

>>> foo = Foo()
... with patch.object(foo, "foo", wraps=foo.foo) as m:
...     print(foo.foo())
"foo"

But this doesn't satisfy my constraint that the object must be instantiated inside the patch context.

解决方案

The problem with my proposed and incorrect solution above

with patch("__main__.Foo.foo", wraps=Foo.foo) as m:
    ...

is that the foo method on Foo is mocked such that it wraps the unbound method Foo.foo, which naturally doesn't work, because the unbound method Foo.foo has no idea which instance it's attached to when called later on.

The simplest solution I could think of

from mock import patch, MagicMock

class Foo:

    def foo(self):
        return "foo"

class MockFoo(Foo):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Every instance of MockFoo will now have its `foo` method 
        # wrapped in a MagicMock
        self.foo = MagicMock(wraps=self.foo)

with patch("__main__.Foo", MockFoo) as m:
    foo = Foo()
    print(foo.foo())
    assert foo.foo.call_count == 1

这篇关于Python mock:包装实例方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆