Batu Lab NotesPractical developer guides

Distinguish a mocked async call from an awaited call

By Batu ยท English technical notes

Also published in our primary archive.

Calling an AsyncMock increments call_count when it creates its awaitable result; it does not prove that result was awaited. So assert_called_once_with("job-7") can pass while the async dependency has not run through an await boundary. Use an await assertion or await_count as the second, separate observation.

This fixture first calls service("job-7") and deliberately keeps the returned coroutine in pending. At that point, the call assertion succeeds, call_count is one, and await_count is zero. The first output line records that contrast. asyncio.run then drives a small coroutine which awaits precisely that captured object. Afterwards the result is "ready", the call count remains one, and the await count becomes one. Every coroutine created by the fixture is consumed.

AsyncMock was added in Python 3.8. Its result is awaitable, and the standard library documents call tracking separately from await tracking, including assert_awaited_once_with. In a real test, use the latter when the contract is that a dependency was awaited with particular arguments; retain a call assertion only when creation of the awaitable is itself relevant. Neither assertion proves work performed by a real dependency, because this fixture substitutes a mock.

See the Python AsyncMock documentation.

AI-assistance disclosure: AI helped draft this synthetic example and explanation.

Example

import asyncio
from unittest.mock import AsyncMock


async def consume(awaitable):
    return await awaitable


service = AsyncMock(return_value="ready")
pending = service("job-7")

service.assert_called_once_with("job-7")
assert service.call_count == 1
assert service.await_count == 0
print(f"before call_count={service.call_count} await_count={service.await_count}")

result = asyncio.run(consume(pending))
service.assert_awaited_once_with("job-7")
assert result == "ready"
assert service.call_count == 1
assert service.await_count == 1
print(f"after result={result} call_count={service.call_count} await_count={service.await_count}")

Expected output:

before call_count=1 await_count=0
after result=ready call_count=1 await_count=1