繁体   English   中英

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

[英]How do I patch a python @classmethod to call my side_effect method?

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

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

但是,我似乎无法修补类方法。

非常感谢帮助!

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 ,修补后的对象不再是MockMagicMockAsyncMockPropertyMock的实例(在剩下的回答中我将只引用Mock因为所有其他都是它的子类)。
只有当您通过例如new=Mock(...)明确指定它是一个或完全省略该属性时,它才是这些的一个实例。
此答案顶部提供的解决方案并非如此。 因此,当您尝试检查函数是否已使用obj.class_method.assert_called()调用时,它会给出一个错误,指出该function has no attribute assert_called ,这是由于修补对象不是实例引起的的Mock ,而是一个function

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

newside_effect之间的结论差异:

  • new指定用什么对象来修补目标(不一定是Mock的实例)
  • side_effect指定在不使用new的情况下使用 patch 时创建的Mock实例的 side_effect 而且它们不能很好地协同工作,因此只能/应该在同一个patch(...)中使用其中一个。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM