我无法在某些方法在内部调用其他方法的类中执行一些基本的
assert_called()
。
示例代码:
from unittest.mock import Mock
class Foo:
def print1(self) -> None:
print("print1 called") # I see this print message
self.print2()
def print2(self) -> None:
print("print2 called") # I see this print message
foo = Foo()
foo_mock = Mock(wraps=foo)
foo_mock.print1()
foo_mock.print1.assert_called() # OK
foo_mock.print2.assert_called() # NOT OK
问题似乎在于
print1(self)
中 self
的实例属于 Foo
类型,而不是 Mock
类型。这就是为什么没有任何关于模拟调用的寄存器print2
。
这是预期的行为吗?通常,
self
绑定到调用者对象。这意味着应该传递 Mock
类型的实例。我猜问题是因为实例已经创建,因此所有方法都绑定到非模拟实例。我希望这会被 Mock
的 __init__
修改。
这个问题有什么解决办法吗?我是不是做错了什么?
编辑:
我发现这个问题可以通过这样做来解决:
import types
from unittest.mock import Mock
class Foo:
def print1(self) -> None:
print("print1 called", type(self))
self.print2()
def print2(self) -> None:
print("print2 called")
foo = Foo()
foo_mock = Mock(wraps=foo)
setattr(foo_mock, "print1", types.MethodType(Mock(wraps=Foo.print1), foo_mock)) # FIX
setattr(foo_mock, "print2", types.MethodType(Mock(wraps=Foo.print2), foo_mock)) # FIX
foo_mock.print1()
foo_mock.print1.assert_called()
foo_mock.print2.assert_called()
问题似乎在于
中print1(self)
的实例属于self
类型,而不是Foo
类型。这就是为什么没有任何关于模拟调用的寄存器Mock
。这是预期的行为吗?print2
是的。
wraps:模拟对象要包装的项目。 如果wraps不是None,那么调用Mock会将调用传递给包装对象(返回真实结果)。模拟上的属性访问将返回一个模拟对象,该对象包装了包装对象的相应属性(因此尝试访问不存在的属性将引发
)。AttributeError
您正在包装
foo
,它是类Foo
的真实实例。任何属性访问都是真实的。使用 wraps
可能会导致真正的 I/O 执行,而您的测试可能没有预料到。仅当您的测试依赖于实际输出时才使用 wraps
。