Python mock:包装实例方法 [英] Python mock: wrap instance method
问题描述
我想要什么:确保在 with
语句中创建的所有 Foo
实例都通过 wraps=Foo 将它们的
.我想要这个的原因是我可以在方法 foo
实例方法包装在 MagicMock 中.foofoo
上跟踪 call_count
为所有创建的 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屋!