在TestCase.setUp()中进行模拟

3 投票
3 回答
4190 浏览
提问于 2025-04-18 17:29

我想要对一个 TestCase 中的所有测试方法进行模拟。

我第一次尝试使用 TestCase.setUp(),但没有成功,因为 setUp() 在测试方法执行之前就结束了。

我不能在 setUp() 里面模拟真实的测试方法:

with mock.patch(...):
    do_something()

我想我可能漏掉了什么。

怎么才能对一个测试案例中的所有方法使用 mock.patch() 呢?

3 个回答

-1

最通用的解决方案,适用于所有上下文管理器是:

import unittest

class TCase(unittest.TestCase):
    def setUp(self):
        self.cm = mock.path(...)
        self.cm.__enter__()

    def test1(self):
        ...

    def tearDown(self):
        self.cm.__exit__(None, None, None)
0

你可以使用 mock.patch.startmock.patch.stop。具体可以查看 这个链接,里面有关于这两个方法的详细说明。

举个例子:

class MyTest(TestCase):

    def setUp(self):
        self.patcher = mock.patch('...')
        self.MockClass = self.patcher.start()

    def tearDown(self):
        self.patcher.stop()

    def test_something(self):
        ....
11

with mock.patch() 是一个 上下文管理器,当代码块结束时,补丁会被撤销。

这意味着当 setUp() 结束时,补丁也会被撤销。

你可以选择使用 @mock.patch() 作为 类装饰器,或者使用 startstop 方法 来控制补丁的应用。

@mock.patch() 作为类装饰器使用,效果和对每个测试方法单独使用装饰器是一样的:

@mock.patch('module.ClassName')
class TestFoo(unittest.TestCase):
    def setUp(self):
        # ...

    def test_one(self, class_mock):
        # ...

    def test_two(self, class_mock):
        # ...

在这里,test_onetest_two 都得到了一个模拟对象,因为 @mock.patch() 类装饰器找到了所有的测试方法并进行了装饰。

使用 start 和 stop 方法可以在 setUptearDown 方法中应用和撤销补丁:

class TestFoo(unittest.TestCase):
    def setUp(self):
        self.patch1 = mock.patch(...)
        self.patch1.start()

    def tearDown(self):
        self.patch1.stop()

在这里,patch1 在设置时启动,并在测试结束时停止。这和上下文管理器的作用类似,但它是与测试的边界相结合。

除了使用 tearDown,你还可以通过 TestCase.addCleanup() 注册 patch.stop() 作为清理函数:

class TestFoo(unittest.TestCase):
    def setUp(self):
        patch1 = mock.patch(...)
        patch1.start()
        self.addCleanup(patch1.stop)

撰写回答