Testing async functions: How to patch a function called by an async function (coroutine)?

Viewed 15

I try to test an async function with pytest that contains a function call I need to patch.

Minimal working example

some_class.py:

from app.services.some_service import do_some_request


class SomeClass():
    def __init__(self):
        self.initialize()

    async def __call__(self, some_parameter):
        # some async function ...

        result = do_some_request(some_parameter)  # should be patched

        if not self.is_result_valid(result):
            raise Exception

        return result

    def is_result_valid(self, result):
        return True

    def initialize(self):
        pass

some_service.py:

def do_some_request(some_parameter):
    return "foo"

some_class_test.py

import pytest
from unittest import mock

from app.api.some_class import SomeClass


@pytest.mark.asyncio
async def test_validation():
    mocked_result = "Mocked result"

    with mock.patch('app.services.some_service.do_some_request', return_value=mocked_result):
        some_class = SomeClass()
        result = await some_class("test")

    assert result == mocked_result

Dependencies

Python 3.8.10

pytest==7.1.3

Result/Problem

Result of Pytest:

tests\some_class_test.py::test_validation FAILED                         [100%]
some_class_test.py:7 (test_validation)
'foo' != 'Mocked result.'

Hence, the patch of do_some_request is not applied during execution of some_class.

Question

Can you give me a hint what I am doing wrong? Or maybe it is not possible to patch a function in such a case?

I also experimented a lot with AsyncMock of unittest.mock and other libraries like asyncio or asynctest with the same result...

0 Answers
Related