python - pytest-mock 补丁上下文管理器在退出时不恢复对象

标签 python pytest pytest-mock

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

模块_a.py

class MyClass:
    def value(self):
        return 10

模块_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 method 方法将被恢复(返回值 10),但是第二个断言语句的测试失败,并出现断言错误 20 != 10 如果我使用完全相同的测试,但将 mocker.patch 替换为 unittest.mock.patch,它就会通过。我认为 pytest-mock 与 unittest.mock 共享相同的 API,所以我很困惑为什么会有差异。

最佳答案

使用pytest-mock,拆卸是在退出 fixture 上下文时完成的。 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,它也可以在 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 想要避免的,以使您的测试更具可读性,因此,如果您不完全使用固定装置进行设置和拆卸,那么您就有点错过了重点。

关于python - pytest-mock 补丁上下文管理器在退出时不恢复对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58294161/

相关文章:

python - Python 中的 Azure 函数无法使用 pymongo

python - 在 Django Admin 中调整字段大小

python - 如何将 Matplotlib.pyplot.loglog 保存到文件?

python - Odoo:动态设置未存储的字段

python - 无法让 PyTest 在 VSCode 或终端中运行。未识别任何测试

python-3.x - pytest - 默认 fixture 参数值

python - 通过 pytest 使用多处理时如何测量覆盖率?

python - 如何在 pytest 中使用 monkeypatch 或 mock 删除库?

python - 修补已修补的类的方法