python 如何创建一个可以start()和stop()的patch.object mock?

t98cgbkg  于 2023-06-20  发布在  Python
关注(0)|答案(1)|浏览(130)

所以我有一个大的Python单元测试套件,我想在所有测试中应用一组4个补丁(禁用昂贵的东西)。
我有超过20个测试类的大约300个测试,我想为我的TestCase提供一个mixin,在setUp中应用这些补丁,而不是单独修补每个类。
我可以使用patch.object来修补每个单独的测试或测试类,这对于300个测试来说是一个语法噩梦,但可以按预期工作:

from django.test import TestCase
from unittest.mock import patch

class MyTestCase(TestCase):

    def test_stuff(self):
        with patch.object('MyClass1', 'mymethod1') as mock_method_1:
            with patch.object('MyClass2', 'mymethod2') as mock_method_2:
                with patch.object('MyClass3', 'mymethod3') as mock_method_3:
                    with patch.object('MyClass4', 'mymethod4') as mock_method_4:
                        # do stuff
                        self.assertEqual(mock_method_4.call_count, 0)

然后我做了一个mixin,在这里我创建了相同的补丁,但将其作为属性添加到测试类中,并使用start()方法。这是完全干燥,我可以修补一切在一次。

class PatchMixin():

    def setUp(self):
        self.mock_method_1 = patch.object(
            MyClass1, "mymethod1"
        )
        self.mock_method_2 = patch.object(
            MyClass2, "mymethod2"
        )
        self.mock_method_3 = patch.object(
            MyClass3, "mymethod3"
        )
        self.mock_method_4 = patch.object(
            MyClass4, "mymethod4"
        )

        self.mock_method_1.start()
        self.mock_method_2.start()
        self.mock_method_3.start()
        self.mock_method_4.start()

        super().setUp()

    def tearDown(self):
        self.mock_method_1.stop()
        self.mock_method_2.stop()
        self.mock_method_3.stop()
        self.mock_method_4.stop()

        super().tearDown(self)

class MyTestCase(TestCase):

    def test_stuff(self):
        # do stuff
        self.assertEqual(self.mock_method_4.call_count, 0)
**THE QUESTION**

When running the mixin, it doesn't work. I get an error:

失败:[未定义]AttributeError:“_patch”对象没有属性“call_count”

Why does this error occur, and how can I use `patch.object` (or some equivalent) to store the patch on my class in this way?
68bkxrlz

68bkxrlz1#

好的我知道了。我以为补丁会被返回,然后应该对它调用start()方法。我没有意识到调用start()的返回值是我应该Assert的补丁(即我应该存储在类中的 that)。
下面是正确的mixin,它按预期工作:

class PatchMixin():

    def setUp(self):
        self.mock_method_1 = patch.object(
            MyClass1, "mymethod1"
        ).start()
        # ... others ...
        super().setUp()

    def tearDown(self):
        self.mock_method_1.stop()
        # ... others ...
        super().tearDown()

相关问题