我们最近已从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,所以对于为什么会有区别感到困惑。
答案 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想要避免的,以使您的测试更具可读性,因此,如果您不完全使用固定装置进行安装和拆卸,则会有些失落。