python 中的 monkeypatch,将模拟泄露给其他测试,导致它们失败
monkeypatch in python, leaking mocks to other tests causing them to fail
我在编写 pytest 单元测试时正在修补其他函数调用,如下所示:
from _pytest.monkeypatch import MonkeyPatch
from third_party import ThirdParty
def test_my_func():
resp1= "resp1"
monkeypatch = MonkeyPatch()
def mock_other_method(*args, **kwargs):
return resp1
monkeypatch.setattr(ThirdParty, "other_method", mock_other_method)
assert ThirdParty().other_method() == "resp1"
# Some assertions
def test_my_func2():
monkeypatch = MonkeyPatch()
expected_result = "This is expected"
result_third_party = ThirdParty().other_method()
assert result_third_party == expected_result
其中,
third_party.py 有:
class ThirdParty:
def other_method(self):
return "This is expected"
这些测试 运行 独立 运行 很好(我刚写的,所以可能有一些语法错误)。但是当我 运行 它作为 pytest -v 时,第二次测试将失败。原因是在调用 other_method 时,它将 return 模拟方法:mock_other_method,并且由于响应不同,它将失败。请提出一些解决方案
我通过在每个测试结束时添加 monkeypatch.undo() 找到了解决方案。这将防止 monkeypatch() 泄漏到其他函数中
monkeypatch
是 pytest fixture 因此
不应该是进口的。相反,您必须在测试函数中将其作为参数提供。 Pytest 在测试开始时加载所有固定装置并按名称查找它们,因此正确的用法是:
from third_party import ThirdParty
# no import from pytest internal module!
def test_my_func(monkeypatch):
resp1 = "resp1"
def mock_other_method(*args, **kwargs):
return resp1
monkeypatch.setattr(ThirdParty, "other_method", mock_other_method)
assert ThirdParty().other_method() == resp1
monkeypatch
fixture 具有函数范围,这意味着补丁将在每个测试函数后自动恢复。
请注意,不鼓励使用内部 pytest
API(例如导入 _pytest
),因为它可能会随着新版本的变化而变化,并且因为有更方便和安全的使用这些功能的方法(而不是最后,因为这些都记录在案)。如果您使用 pytest
或 pytest
插件提供的夹具,您永远不应该自己操心清理夹具 - 很容易忘记清理并产生不必要的副作用。
我在编写 pytest 单元测试时正在修补其他函数调用,如下所示:
from _pytest.monkeypatch import MonkeyPatch
from third_party import ThirdParty
def test_my_func():
resp1= "resp1"
monkeypatch = MonkeyPatch()
def mock_other_method(*args, **kwargs):
return resp1
monkeypatch.setattr(ThirdParty, "other_method", mock_other_method)
assert ThirdParty().other_method() == "resp1"
# Some assertions
def test_my_func2():
monkeypatch = MonkeyPatch()
expected_result = "This is expected"
result_third_party = ThirdParty().other_method()
assert result_third_party == expected_result
其中, third_party.py 有:
class ThirdParty:
def other_method(self):
return "This is expected"
这些测试 运行 独立 运行 很好(我刚写的,所以可能有一些语法错误)。但是当我 运行 它作为 pytest -v 时,第二次测试将失败。原因是在调用 other_method 时,它将 return 模拟方法:mock_other_method,并且由于响应不同,它将失败。请提出一些解决方案
我通过在每个测试结束时添加 monkeypatch.undo() 找到了解决方案。这将防止 monkeypatch() 泄漏到其他函数中
monkeypatch
是 pytest fixture 因此
不应该是进口的。相反,您必须在测试函数中将其作为参数提供。 Pytest 在测试开始时加载所有固定装置并按名称查找它们,因此正确的用法是:
from third_party import ThirdParty
# no import from pytest internal module!
def test_my_func(monkeypatch):
resp1 = "resp1"
def mock_other_method(*args, **kwargs):
return resp1
monkeypatch.setattr(ThirdParty, "other_method", mock_other_method)
assert ThirdParty().other_method() == resp1
monkeypatch
fixture 具有函数范围,这意味着补丁将在每个测试函数后自动恢复。
请注意,不鼓励使用内部 pytest
API(例如导入 _pytest
),因为它可能会随着新版本的变化而变化,并且因为有更方便和安全的使用这些功能的方法(而不是最后,因为这些都记录在案)。如果您使用 pytest
或 pytest
插件提供的夹具,您永远不应该自己操心清理夹具 - 很容易忘记清理并产生不必要的副作用。