[英]How do I patch a python @classmethod to call my side_effect method?
The following code shows the problem.下面的代码显示了这个问题。
I can successfully patch object instance and static methods of this SomeClass
我可以成功地修补这个
SomeClass
的对象实例和静态方法
However, I can't seem to be able to patch classmethods.但是,我似乎无法修补类方法。
Help much appreciated!非常感谢帮助!
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()
A way to patch a classmethod would be to use new=classmethod(class_method)
instead of side_effects=class_method
.修补类方法的一种方法是使用
new=classmethod(class_method)
而不是side_effects=class_method
。
This works pretty well in general.这在一般情况下工作得很好。
Using new
, the patched object isn't necessarily an instance of Mock
, MagicMock
, AsyncMock
or PropertyMock
anymore (During the rest of the answer i'll only reference Mock
as all the others are subclasses of it).使用
new
,修补后的对象不再是Mock
、 MagicMock
、 AsyncMock
或PropertyMock
的实例(在剩下的回答中我将只引用Mock
因为所有其他都是它的子类)。
It is only then an instance of these when you explicitly specify it to be one via eg new=Mock(...)
or ommit the attribute completely.只有当您通过例如
new=Mock(...)
明确指定它是一个或完全省略该属性时,它才是这些的一个实例。
That wouldn't be the case with the solution provided at the top of this answer.此答案顶部提供的解决方案并非如此。 So when you try to eg check if the function already got called using
obj.class_method.assert_called()
, it'll give an error saying that function has no attribute assert_called
which is caused by the fact that the patched object isn't an instance of Mock
, but instead a function
.因此,当您尝试检查函数是否已使用
obj.class_method.assert_called()
调用时,它会给出一个错误,指出该function has no attribute assert_called
,这是由于修补对象不是实例引起的的Mock
,而是一个function
。
Unfortunately I don't see any solution to this downside in that scenario at the moment不幸的是,目前我没有看到任何解决方案来解决这种情况
new
and side_effect
: new
和side_effect
之间的结论差异:new
specifies what object to patch the target with (doesn't necessarily have to be an instance of Mock
) new
指定用什么对象来修补目标(不一定是Mock
的实例)side_effect
specifies the side_effect of the Mock
instance that gets created when using patch without new
Also they don't play very well together, so only one of these can/should be used in the same patch(...)
. side_effect
指定在不使用new
的情况下使用 patch 时创建的Mock
实例的 side_effect 而且它们不能很好地协同工作,因此只能/应该在同一个patch(...)
中使用其中一个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.