pytest-mock 补丁上下文管理器不在退出时恢复对象
pytest-mock patch context manager not restoring object on exit
我们最近从 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 的值方法方法将被恢复(return 值为 10),但是第二个断言语句的测试失败并出现断言错误 20 != 10
如果我使用完全相同的测试,但将 mocker.patch
替换为 unittest.mock.patch
,它会通过。我认为 pytest-mock 与 unittest.mock 共享相同的 API,所以我很困惑为什么会有差异。
使用 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,它在 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 打算避免的,以使您的测试更具可读性,因此如果您不完全使用固定装置进行设置和拆卸,您就有点忽略了重点。
我们最近从 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 的值方法方法将被恢复(return 值为 10),但是第二个断言语句的测试失败并出现断言错误 20 != 10
如果我使用完全相同的测试,但将 mocker.patch
替换为 unittest.mock.patch
,它会通过。我认为 pytest-mock 与 unittest.mock 共享相同的 API,所以我很困惑为什么会有差异。
使用 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,它在 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 打算避免的,以使您的测试更具可读性,因此如果您不完全使用固定装置进行设置和拆卸,您就有点忽略了重点。