Python mock fix a coroutine function in another function using pytest?
I have two functions in module_name / app.py
async def f1(arg):
# do something
return arg + '1'
async def f2(arg):
result = await f1(arg)
return result
I am trying to test f2 and mock f1 with pytest and asynctest.
It only works if I do
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')
test PASSED
But I want to do something like this
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')
I get
assert 'some value' == await f2('test')
AssertionError: assert 'some value' == 'test1'
- some value
+ test1
Why doesn't the second method work?
source to share
In your second example in mock_f1
fixture, you create an object CoroutineMock
and return it. But you don't overwrite the function module_name.app.f1
: Mock
-like objects don't patch anything automatically.
Here's an example adding to your example:
@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')
Which will print something like this
fixture value: <CoroutineMock spec='function' id='139756096130688'>
actual module_name.app.f1 function: <function f1 at 0x7f1b7e1139d8>
When you call f2
it uses a function f1
from the module that is not overridden.
So, this is how it would work for you:
@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
As you probably know, it monkeypatch
will make sure that the changes are applied only when the fixture is active.
source to share