修补模拟类的方法

时间:2020-03-04 16:03:46

标签: python unit-testing mocking monkeypatching

我的代码具有以下结构:

我有一个类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()

2 个答案:

答案 0 :(得分:0)

我在下一页找到了答案的线索,其中讨论了模拟嵌套属性调用: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实际上是staticmethod,因此应如下所示:

class Substitute:

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

答案 1 :(得分:-1)

要模拟类中的方法以返回特定值,请使用@patch。目的。用@patch模拟类中的方法。对象,但每次调用时都返回不同的值,请使用side_effect。