【问题标题】:External library mock patch used in all tests doesnt work when tests run together当测试一起运行时,所有测试中使用的外部库模拟补丁不起作用
【发布时间】:2018-06-25 10:32:38
【问题描述】:

我正在使用 Python 的模拟库和 unittest。我正在为一个在其方法之一中使用外部库函数的类编写单元测试。根据不同的情况,这个函数返回不同的值。

假设我想测试 A 类:

from external_library import function_foo

class A(object):
...

在我的测试类中,为了使用函数从外部库返回的值,我创建了一个补丁,并且在定义补丁后才导入类 A。但是,我需要在我所有的测试方法中使用这个函数,并且在每个方法中它返回不同的值。

我的测试类如下:

class TestA(TestCase):

    @patch('external_library.function_foo', side_effect=[1, 2, 3])    
    def test_1(self, *patches):

       from module import class A
       obj = A()
       ...

    @patch('external_library.function_foo', side_effect=[1, 1, 2, 2, 3, 3])    
    def test_2(self, *patches):

       from module import class A
       obj = A()
       ...

    ...

我有 10 个测试,当我一起运行所有测试时,只有 1 个(第一个)通过,其余的,我得到 StopIteration 错误。但是,如果我单独运行它们中的每一个,它们都会通过

我尝试在每种方法中使用with patch('external_library.function_foo', side_effect=[...]),但结果是一样的。我还尝试在setUp 方法中只创建一次补丁,启动它,在每个方法中重新分配side_effect,然后在tearDown 中停止,但它不起作用。

对在这种情况下可能起作用的任何想法?

谢谢!

【问题讨论】:

    标签: python unit-testing mocking python-unittest


    【解决方案1】:

    需要注意的是,第二次导入模块 it would not be loaded again 时,会得到与第一次导入时相同的模块对象。

    当您第一次运行“test_1”时,external_library.function_fooMock 对象替换,我们将其命名为 mock_a。然后你的“模块”第一次被导入,python 将加载它,意思是,在“模块”中执行代码,它将名称“function_foo”绑定到“模块”命名空间中的对象“mock_a”,保存“模块”反对sys.modules。这次您的测试将通过,mock_a 中的 side_effect 会被消耗掉。

    接下来是“test_2”,external_library.function_foo 替换为Mock 对象,将其命名为mock_b。然后导入“module”,这次它不会再次加载,而是从sys.modules 填充,你会得到与“test_1”中相同的模块对象。在这个模块对象的命名空间中,名称“function_foo”仍然绑定到对象mock_a,而不是新创建的mock_b。因为mock_aside_effect 已经消费了,所以出现StopIteration 错误。

    你应该在 name 被查找的地方应用补丁,而不是它被定义的地方:

    @patch('module.function_foo', side_effect=[1, 2, 3])    
    def test_1(self, patch):
        ...
    

    阅读"Where to patch" section of the manual of patch的更多详细信息。

    【讨论】:

    • 感谢您的回答和@georgexsh 的精彩解释,我通过将external_library.function_foo 替换为package.module.function_foo 来实现它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-15
    • 2017-02-10
    • 1970-01-01
    相关资源
    最近更新 更多