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?

+3


source to share


1 answer


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.

+2


source







All Articles