首页 > 解决方案 > 修补模拟类的方法

问题描述

我的代码具有以下结构:

我有一个MyClass继承自的类BaseClass(这是一个偶然的点,而不是我的问题的根源)。然后我有另一个类MyClassManager调用MyClass.

我正在为一种方法编写单元测试,MyClassManager并且我想控制其中一种方法的返回值,MyClass同时自动指定其余方法。

在我的测试中,我MyClass通过使用autospec=True. 然后我尝试修补该方法MyClass.method_to_patch并将其替换为Substitute.substitute_method. 到现在为止还挺好。

但是现在当我运行测试时,类管理器会创建MyClass一个完全自动指定的 Mock 实例,但它不会修补我想要替换的方法。

有没有办法结合这两个patch装饰器来实现我想要的?

class Substitute:

    def substitute_method(self, arg1, arg2):
        print("Running substitute method")
        return (arg1 > 0 and arg2 > 0)


class BaseClass:

    def method_to_patch(self, arg1, arg2):
        return arg1 == arg2


class MyClass(BaseClass):

    def myclass_method(self):
        print("myclass method called")


class MyClassManager:

    def method_to_test(self):
        my_class = MyClass()
        my_class.myclass_method()
        my_class.method_to_patch(10, 100)


class TestMyClass(unittest.TestCase):

    @patch.object(MyClass, "method_to_patch", Substitute.substitute_method)
    @patch("__main__.MyClass", autospec=True)
    def test_method_to_test(self, mock_class):
        class_manager = MyClassManager()
        class_manager.method_to_test()
        print(mock_class.call_count)


if __name__ == "__main__":
    unittest.main()

标签: pythonunit-testingmockingmonkeypatching

解决方案


我在以下页面中找到了答案的线索,它讨论了模拟嵌套属性调用:https ://www.integralist.co.uk/posts/mocking-in-python/ 。相同的逻辑适用于方法调用。

手动调整模拟对象是不够的 - 您必须调整return_value模拟对象的 。

所以这里是测试的样子:

class TestMyClass(unittest.TestCase):

    @patch("__main__.MyClass", autospec=True)
    def test_method_to_test(self, mock_class):
        mock_class.return_value.method_to_patch = Substitute.substitute_method
        class_manager = MyClassManager()
        class_manager.method_to_test()
        print(mock_class.call_count)

现在我有一个模拟对象来代替,MyClass所以MyClass.myclass_method也被模拟了,但是我可以根据需要Substitute.substitute_method替换MyClass.method_to_patch

最后一点 -substitute_method实际上是 astaticmethod所以它应该是这样的:

class Substitute:

    @staticmethod
    def substitute_method(arg1, arg2):
        print("Running substitute method")
        return (arg1 > 0 and arg2 > 0)

推荐阅读