4

我们最近从 unittest 切换到 pytest。我在mocker.patch用作上下文管理器时遇到了一个奇怪的问题。考虑以下示例。

module_a.py

class MyClass:
    def value(self):
        return 10

module_b.py

import module_a
class AnotherClass:
    def get_value(self):
        return module_a.MyClass().value()

test_module_b.py

from module_b import AnotherClass
def test_main_2(mocker):
    with mocker.patch('module_a.MyClass.value', return_value=20):
        value = AnotherClass().get_value()
        assert value == 20
    value = AnotherClass().get_value()
    assert value == 10

我希望一旦上下文管理器退出,MyClass 的 value 方法方法将被恢复(返回值为 10),但是测试在第二个断言语句上失败并出现断言错误20 != 10如果我使用完全相同的测试,但替换mocker.patchunittest.mock.patch,它通过。我认为 pytest-mock 与 unittest.mock 共享相同的 API,所以我对为什么会有差异感到困惑。

4

1 回答 1

3

使用pytest-mock,在退出夹具上下文时完成拆卸。该mocker.patch对象不仅仅是mock.patch.

在编写 pytest 风格的测试时,您不应该在测试函数中需要上下文管理器,事实上pytest-mock 插件的目的是使用上下文管理器和函数装饰器来模拟不必要的.

如果由于某种原因您确实需要从测试本身中进行拆卸步骤那么您需要在 pytest 中也可以正常工作的普通旧模拟 API。

from unittest.mock import patch

def test_main_2():
    with patch('module_a.MyClass.value', return_value=20):
        value = AnotherClass().get_value()
        assert value == 20
    value = AnotherClass().get_value()
    assert value == 10

请注意,这种嵌套结构确实是 pytest 打算避免的,以使您的测试更具可读性,因此,如果您不完全使用固定装置进行设置和拆卸,那么您有点错过了重点。

于 2019-10-08T21:28:01.120 回答