Python 使用 pytest 在另一个函数中模拟修补协程函数?
Python mock patch a coroutine function within another function using pytest?
我在 module_name/app.py
中有两个函数
async def f1(arg):
# do something
return arg + '1'
async def f2(arg):
result = await f1(arg)
return result
我尝试使用 pytest 和 asynctest 测试 f2 和 mock f1。
只有我这样做才有效
def sf_f1(arg):
return 'some value'
@pytest.mark.asyncio
async def test_f2():
with asynctest.mock.patch('module_name.app.f1', side_effect=sf_f1):
assert 'some value' == await f2('test')
测试通过
但是,我想做这样的事情
import module_name
@pytest.fixture()
def mock_f1():
return asynctest.CoroutineMock(module_name.app.f1, side_effect=sf_f1)
@pytest.mark.asyncio
async def test_f2_2(mock_f1):
assert 'some value' == await f2('test')
我明白了
assert 'some value' == await f2('test')
AssertionError: assert 'some value' == 'test1'
- some value
+ test1
为什么第二种方式不行?
在您的第二个示例中,您在 mock_f1
夹具中创建了一个 CoroutineMock
对象并 return 它。但是你不要覆盖 module_name.app.f1
函数:Mock
-like 对象不会自动修补任何东西。
这是对您的示例的补充说明:
@pytest.mark.asyncio
async def test_f2_2(mock_f1):
print('fixture value:', mock_f1)
print('actual module_name.app.f1 function:', module_name.app.f1)
assert 'some value' == await f2('test')
这会打印出类似这样的东西
fixture value: <CoroutineMock spec='function' id='139756096130688'>
actual module_name.app.f1 function: <function f1 at 0x7f1b7e1139d8>
当您调用 f2
时,它使用模块中的 f1
函数,该函数未被覆盖。
所以这是适合您的方法:
@pytest.fixture
def mock_f1(monkeypatch):
fake_f1 = asynctest.CoroutineMock(module_name.app.f1, side_effect=sf_f1)
monkeypatch.setattr(module_name.app, 'f1', fake_f1)
return fake_f1
您可能知道,monkeypatch
将确保仅在灯具处于活动状态时应用更改。
我在 module_name/app.py
中有两个函数async def f1(arg):
# do something
return arg + '1'
async def f2(arg):
result = await f1(arg)
return result
我尝试使用 pytest 和 asynctest 测试 f2 和 mock f1。
只有我这样做才有效
def sf_f1(arg):
return 'some value'
@pytest.mark.asyncio
async def test_f2():
with asynctest.mock.patch('module_name.app.f1', side_effect=sf_f1):
assert 'some value' == await f2('test')
测试通过
但是,我想做这样的事情
import module_name
@pytest.fixture()
def mock_f1():
return asynctest.CoroutineMock(module_name.app.f1, side_effect=sf_f1)
@pytest.mark.asyncio
async def test_f2_2(mock_f1):
assert 'some value' == await f2('test')
我明白了
assert 'some value' == await f2('test')
AssertionError: assert 'some value' == 'test1'
- some value
+ test1
为什么第二种方式不行?
在您的第二个示例中,您在 mock_f1
夹具中创建了一个 CoroutineMock
对象并 return 它。但是你不要覆盖 module_name.app.f1
函数:Mock
-like 对象不会自动修补任何东西。
这是对您的示例的补充说明:
@pytest.mark.asyncio
async def test_f2_2(mock_f1):
print('fixture value:', mock_f1)
print('actual module_name.app.f1 function:', module_name.app.f1)
assert 'some value' == await f2('test')
这会打印出类似这样的东西
fixture value: <CoroutineMock spec='function' id='139756096130688'>
actual module_name.app.f1 function: <function f1 at 0x7f1b7e1139d8>
当您调用 f2
时,它使用模块中的 f1
函数,该函数未被覆盖。
所以这是适合您的方法:
@pytest.fixture
def mock_f1(monkeypatch):
fake_f1 = asynctest.CoroutineMock(module_name.app.f1, side_effect=sf_f1)
monkeypatch.setattr(module_name.app, 'f1', fake_f1)
return fake_f1
您可能知道,monkeypatch
将确保仅在灯具处于活动状态时应用更改。