我如何修补一个python @classmethod调用我的side_effect方法?



下面的代码显示了这个问题。

我可以成功地修补这个SomeClass的对象实例和静态方法

但是,我似乎无法修补classmethods。

帮助非常感谢!

from contextlib import ExitStack
from unittest.mock import patch

class SomeClass:
def instance_method(self):
print("instance_method")
@staticmethod
def static_method():
print("static_method")
@classmethod
def class_method(cls):
print("class_method")
# --- desired patch side effect methods ----
def instance_method(self):
print("mocked instance_method")
def static_method():
print("mocked static_method")
def class_method(cls):
print("mocked class_method")
# --- Test ---
obj = SomeClass()
with ExitStack() as stack:
stack.enter_context(
patch.object(
SomeClass,
"instance_method",
side_effect=instance_method,
autospec=True
)
)
stack.enter_context(
patch.object(
SomeClass,
"static_method",
side_effect=static_method,
# autospec=True,
)
)
stack.enter_context(
patch.object(
SomeClass,
"class_method",
side_effect=class_method,
# autospec=True
)
)

# These work
obj.instance_method()
obj.static_method()
# This fails with TypeError: class_method() missing 1 required positional argument: 'cls'
obj.class_method()

通解

修补类方法的一种方法是使用new=classmethod(class_method)而不是side_effects=class_method.
这在一般情况下效果很好。

缺点使用new,补丁对象不一定是Mock,MagicMock,AsyncMockPropertyMock的实例(在回答的其余部分,我将只引用Mock,因为所有其他都是它的子类)。
只有当您通过例如new=Mock(...)或完全提交属性显式指定它为一个实例时,它才是这些实例的实例。
在这个答案的顶部提供的解决方案不会是这种情况。因此,当你尝试检查函数是否已经使用obj.class_method.assert_called()被调用时,它会给出一个错误,说function has no attribute assert_called,这是由于补丁对象不是Mock的实例,而是function

不幸的是,目前在这种情况下,我看不到任何解决方案

newside_effect的结论差异:

  • new指定要给目标打补丁的对象(不一定是Mock的实例)
  • side_effect指定当使用补丁而不使用new时创建的Mock实例的副作用他们也不能很好地发挥,所以只有一个可以/应该在同一个patch(...)中使用。

相关内容

  • 没有找到相关文章

最新更新