Python补丁装饰器影响其他方法

8 投票
1 回答
2349 浏览
提问于 2025-04-28 04:37

我的理解是,当你在单元测试中使用补丁装饰器时(我用的是nose框架),这个补丁装饰器的作用范围就是这个测试用例的范围。问题在这里:

@patch('a')
@patch('b')
@patch('b')
def test_add_stuff(self, mock_a, mock_b, mock_c):
    url = '/path/blah/blah'
    assert_true(stuff)
    # Now those three patch decorators should be "done"


def test_delete_stuff(self):
    url = '/another_path/not_important'
    assert_true(something)

在我的第二个测试用例test_delete_stuff中,我在实际代码里加了一个打印语句,目的是为了调试一个抛出的错误。结果发现,在通过网址访问的控制器动作中,有一个函数调用返回了一个MagicMock对象!这个对象是来自之前测试用例的mock_b。

如果我只是把这两个测试用例的顺序反过来,结果也没有变化。如果我把带有补丁装饰器的那个测试注释掉,我的第二个测试用例就能通过了。

补充信息: 在这些实例方法所在的类上没有补丁装饰器。

有什么想法吗?

--更新--

结果发现,我没有在函数调用被查找的地方进行模拟,这解决了问题。不过,这并没有解释为什么补丁的作用范围会超过一个测试用例。

如果控制器只有在发送GET请求时才会被实例化,并且控制器文件中的导入被模拟了,为什么MagicMock对象会在多个单元测试中持续存在呢?

暂无标签

1 个回答

1

我想问题出在路径范围上,因为你在 TestCase 类中修改了方法。你可以在官方的 Python unittest.patch 文档中找到相关信息:

Patch 可以作为一个 TestCase 类的装饰器使用。它的工作原理是给类中的每个测试方法添加装饰。这可以减少当你的测试方法共享一组公共补丁时的重复代码。patch() 通过查找以 patch.TEST_PREFIX 开头的方法名来找到测试。默认情况下,这个前缀是 'test',这与 unittest 查找测试的方法一致。你也可以通过设置 patch.TEST_PREFIX 来指定一个不同的前缀。

所以所有以 test 开头的方法都会被添加上补丁。这是默认的行为。

撰写回答