pytest-mock修补程序上下文管理器无法在退出时还原对象

时间:2019-10-08 21:13:28

标签: python pytest pytest-mock

我们最近已从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),但是如果第二个assert语句的测试失败,则将出现断言错误20 != 10相同的测试,但是将mocker.patch替换为unittest.mock.patch,则通过。我以为pytest-mock与unittest.mock共享相同的API,所以对于为什么会有区别感到困惑。

1 个答案:

答案 0 :(得分:1)

使用pytest-mock,在退出灯具上下文时进行拆卸。 mocker.patch对象不仅是mock.patch的简单别名。

编写pytest风格的测试,实际上是the purpose of the pytest-mock plugin is to make the use of context managers and function decorators for mocking unnecessary时,在测试函数中不需要上下文管理器。

如果出于某种原因您确实需要在测试本身的 中进行拆卸,那么您希望使用普通的旧模拟API,该API在pytest中也可以正常工作。

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想要避免的,以使您的测试更具可读性,因此,如果您不完全使用固定装置进行安装和拆卸,则会有些失落。