Skip to content

unittesting_async

Carter Tinney edited this page Sep 9, 2019 · 1 revision

Testing with Async/Await

Our tooling is currently flawed for testing coroutine functions, as coroutine functions return asyncio.Future objects rather than the result of the call. This makes mocking tricky, even when using both the pytest-mock and pytest-asyncio extensions.

In order to mock a coroutine function/method to A) return a value, and B) not hang forever, do something like the following:

async def create_completed_future(result=None):
    f = asyncio.Future()
    f.set_result(result)
    return f

@pytest.mark.describe("Foo - Bar")
class TestBar(object):

    @pytest.mark.it("Returns 'buzz' when called")
    async def test_returns_buzz(self, mocker):
        foo = FooClient()

        mocker.patch(foo, "bar", return_value=(await create_completed_future("buzz")))

        res = await foo.bar()

        assert res == "buzz"

As you can see, by returning a completed future the mocked coroutine method was able to be compatible with the await syntax. Additionally, the result of the future was set to the mocked return value, which was then transferred to the variable res after the await was resolved.