skip to content

unittest.mock

The stdlib mocking library — building stand-ins, patching a name for one test, scripting behavior, asserting calls. Its permissive defaults are easy to misuse, so it is a dense source of questions.

part ofPythonoverview, primer and where to startread it →
on this pageshow

questions

23

What does calling a unittest.mock.AsyncMock return, and how does that differ from Mock?

level: juniorimportance: must knowfreq 60%

answer

  1. The call runs none of the real body
  2. The call hands back something unfinished
  3. You must await what the call returned
  4. A coroutine object; await yields return_value
  5. Awaiting a MagicMock raises TypeError

basics

~10 s

Calling an AsyncMock runs nothing and hands back a coroutine object; awaiting that coroutine produces the mock's return_value. A plain Mock returns its return_value immediately, and awaiting a Mock raises TypeError.

solid answer

~40 s

`unittest.mock.AsyncMock` is the double for a coroutine function. Calling it records the call and returns a coroutine object without producing anything; the configured `return_value` is delivered only when that coroutine is awaited, so `await double(1)` gives the configured result while a bare `double(1)` leaves an unawaited coroutine and a `RuntimeWarning` that it was never awaited. `return_value` is a plain value — you do not wrap it in a future. `side_effect` accepts the usual shapes plus an async callable, which the mock awaits. A synchronous `Mock` or `MagicMock` cannot stand in: on Python 3.14 awaiting one raises `TypeError: 'MagicMock' object can't be awaited`. `AsyncMock` subclasses `MagicMock`, so `__aenter__` and `__aexit__` on it are AsyncMocks too, and `inspect.iscoroutinefunction(AsyncMock())` returns `True`.

code

python · 14 lines
python
import asyncio
from unittest.mock import AsyncMock, MagicMock

fetch = AsyncMock(return_value={"id": 7})

async def main():
    fetch()                       # creates a coroutine object, runs nothing
    print(await fetch())          # {'id': 7}
    try:
        await MagicMock()
    except TypeError as exc:
        print(exc)                # 'MagicMock' object can't be awaited

asyncio.run(main())

go deeper

for a junior

Be ready to say in one sentence that calling an AsyncMock gives you a coroutine and that awaiting it gives you return_value. Knowing that a plain Mock cannot be awaited is the other half interviewers listen for.

for a middle

Explain the mechanics: the call records call_count and builds the coroutine, the await records await_count and applies side_effect or return_value. Mention that return_value is a plain value needing no future wrapper.

for a senior

Show the diagnosis habit — treat the never-awaited RuntimeWarning as a real failure signal, turn warnings into errors in CI, and assert on awaits so a missing await in production code cannot slip past a green suite.

for a principal

Own the convention: which doubles a codebase uses for async boundaries, whether unawaited-coroutine warnings are errors in the pipeline, and how the team avoids doubles that are shaped differently from the objects they replace.

`unittest.mock.AsyncMock` is the test double for a **coroutine function** — something defined with `async def`. It exists because a plain `Mock` gets the shape of an async call wrong in a way that either explodes or, worse, passes quietly. ### What a call does, and what an await does Two separate events happen when production code runs `result = await double(item_id)`. 1. **The call.** `double(item_id)` invokes the mock. `AsyncMock.__call__` records the call in `call_count`/`call_args_list` exactly as `Mock` does, and then returns a **coroutine object**. Nothing you configured has been produced yet; no `side_effect` has run. 2. **The await.** Awaiting that coroutine object is what makes the mock produce a value. It records the await in `await_count`/`await_args`/`await_args_list`, applies `side_effect` if one is set, and otherwise returns `return_value`. The practical consequence is that `return_value` is a **plain value**, not something you have to wrap. `AsyncMock(return_value={"id": 7})` makes `await double()` produce `{"id": 7}`. Candidates who learned mocking on Python 3.7 often still wrap results in a future or hand-roll a coroutine function; on 3.8 and later that is not only unnecessary, it is wrong — the await then yields the future object rather than the value inside it. Reach for a real awaitable only when the code under test treats the returned object as a future in its own right, for instance by cancelling it or attaching a done callback. `side_effect` on an `AsyncMock` accepts the same shapes as on `Mock` — an exception instance or class, an iterable of results, a callable — plus one extra: an **async** callable, which the mock awaits and whose result it returns. That is the clean way to compute a per-call answer or to raise only for particular arguments. ### The two ways to get it wrong **Forgetting the await in production code.** If the code under test calls the double but never awaits it, the coroutine object is created, dropped and eventually garbage-collected, and CPython emits `RuntimeWarning: coroutine 'AsyncMockMixin._execute_mock_call' was never awaited`. That warning is easy to lose in a noisy test log, so it is worth turning warnings into errors in CI, and better still to assert on the mock's `await_count` rather than trusting a warning to surface. This is the single most valuable thing `AsyncMock` gives you: real code that forgets an `await` produces a double that was *called* but never *awaited*, and only an await assertion notices. **Using a synchronous double where a coroutine function is expected.** Awaiting a `Mock` or `MagicMock` raises `TypeError`. On Python 3.14 the message reads `'MagicMock' object can't be awaited`; through 3.13 the same condition read `object MagicMock can't be used in 'await' expression`, so never assert on that string in a test. This failure is loud, which makes it the friendly one — the dangerous case is the reverse, where an async double stands in for something the code never awaits. ### How AsyncMock relates to the rest of the family `AsyncMock` subclasses `MagicMock`, so it inherits the pre-configured magic methods and adds the asynchronous ones: `__aenter__`, `__aexit__` and `__anext__` on any `MagicMock` or `AsyncMock` are themselves `AsyncMock` instances, which is why an `async with` over a `MagicMock` works out of the box. The double also advertises itself convincingly: `inspect.iscoroutinefunction(AsyncMock())` returns `True`, so production code that branches on that check still takes its async path. Conversely, not every async-looking thing needs an `AsyncMock`. A **synchronous** function that returns an awaitable — a factory that hands back a task or a coroutine — is not a coroutine function. Its double should be a `MagicMock` whose `return_value` is awaitable. Matching the double to the real object's shape, rather than to the presence of the word "async" nearby, is the whole skill. ### Reading a failure Three symptoms map cleanly back to this model, and recognising them saves a long hunt. `TypeError: 'MagicMock' object can't be awaited` means a synchronous double sits where a coroutine function belongs. `RuntimeWarning: coroutine ... was never awaited` means an async double was called by code that did not await it — either a real bug in the code under test, or a double that should have been synchronous. And an assertion that reports a mock was never awaited, while the call assertion for the same arguments passes, means the coroutine was created and dropped somewhere in between. ### What AsyncMock does not give you It is a double, not a scheduler. Constructing one needs no running event loop, and it introduces no concurrency of its own: the await resolves immediately, in order, with no suspension point that another task can slip through. That is usually what you want in a unit test, but it means an `AsyncMock` cannot reproduce interleaving bugs — a double that always completes instantly will never show you the window in which two tasks race. Timing-shaped behaviour has to be modelled explicitly, for instance with an async `side_effect` that awaits before returning. ### Version notes `AsyncMock`, the await assertions, and automatic async magic-method support all arrived in Python 3.8. Nothing about that core behaviour changed through 3.14; only the wording of the `TypeError` raised when a non-async mock is awaited was rewritten in 3.14.

  • What does CPython report when the code under test calls your AsyncMock but never awaits it?
    When the orphaned coroutine object is collected, CPython emits `RuntimeWarning: coroutine 'AsyncMockMixin._execute_mock_call' was never awaited`. It is easy to lose in test output, so turn warnings into errors in CI and, more reliably, assert on the mock's `await_count` instead of trusting a warning to surface.
  • Do you have to wrap an AsyncMock's return_value in a coroutine or a future yourself?
    No. Assign the plain value — `double.return_value = {'id': 7}` — and the await produces it. Wrapping it means the await yields the wrapper object instead of the value. Build a real awaitable only when the code under test treats the result as a future in its own right, for example by cancelling it or attaching a done callback.
  • What extra shape does side_effect accept on an AsyncMock that it does not on Mock?
    An async callable. The mock awaits it and returns its result, which is the clean way to compute a per-call answer or raise only for particular arguments. Exceptions, iterables of results and plain callables behave as they do on a synchronous mock; the awaited callable is the addition.

Calling an AsyncMock is like being handed a sealed order ticket: the ticket records that you asked, but nothing is prepared until you take it to the counter and wait.

saying these in an interview costs you the question

  • Thinks calling an AsyncMock runs the real coroutine body
  • Wraps return_value in a future or coroutine needlessly
  • Believes a plain Mock works inside an await expression
  • Ignores the never-awaited RuntimeWarning in test output
  • Confuses the returned coroutine with the awaited value

context

open as a page

What does Mock.assert_called_once_with check that Mock.assert_called_with does not?

level: juniorimportance: must knowfreq 68%

basics

~10 s

assert_called_with only inspects the mock's most recent call. assert_called_once_with additionally requires that the mock was called exactly once, so a second, accidental call fails the test.

open as a page

What does unittest.mock.MagicMock configure that a plain Mock does not?

level: juniorimportance: must knowfreq 62%

basics

~10 s

MagicMock preconfigures the magic dunder methods, such as len, iter, bool and the context-manager pair, with working defaults. A plain Mock invents ordinary attributes only, so calling len() on one raises TypeError.

open as a page

How does unittest.mock.mock_open let you test a function that reads a file?

level: juniorimportance: must knowfreq 60%

basics

~20 s

unittest.mock.mock_open(read_data="...") builds a MagicMock that stands in for the builtin open. Patch open with it, and the handle the code receives serves that text from read, readline, readlines and iteration, without touching a real file.

open as a page

What are the three ways to apply unittest.mock.patch, and when is each right?

level: juniorimportance: must knowfreq 60%

basics

~20 s

unittest.mock.patch can be used as a decorator on a test function or class, as a with-statement context manager, or started and stopped by hand through a patcher object. Every form puts the original attribute back when its scope ends.

open as a page

In unittest.mock, what does a Mock's return_value attribute control?

level: juniorimportance: must knowfreq 70%

basics

~10 s

return_value is the object a Mock hands back on every call, whatever arguments it receives. Setting client.evaluate.return_value to a dict makes every client.evaluate(...) call return that same dict object, not a fresh copy.

open as a page

How do AsyncMock's await assertions differ from call assertions like assert_called_once_with?

level: middleimportance: must knowfreq 55%

basics

~20 s

An AsyncMock keeps two ledgers: call_count records when it was invoked and a coroutine created, await_count records when that coroutine was actually awaited. assert_awaited_once_with checks the await ledger, so it catches a missing await that call assertions happily pass.

open as a page

Why does a bare unittest.mock.Mock accept calls to methods the real object lacks?

level: middleimportance: must knowfreq 58%

basics

~20 s

A Mock invents a child mock for any attribute name on first touch, so a typo or a renamed method still returns something callable and the test passes. spec= or spec_set= pins it to a real object's attributes.

open as a page

How do you assert what your code wrote through a mock_open file handle?

level: middleimportance: must knowfreq 50%

basics

~10 s

Reach the handle through the mock's return_value, then assert on its write child: assert_called_once_with for a single write, or join the first argument of every call in handle.write.call_args_list to rebuild the whole document.

open as a page

Why must unittest.mock.patch target where a name is looked up, not where it is defined?

level: middleimportance: must knowfreq 72%

basics

~20 s

A from-import copies the referenced object into the importing module's own namespace, so replacing the attribute in the defining module leaves that copy untouched and the patch does nothing. Patch the name in the module under test instead.

open as a page

What three kinds of value can unittest.mock's side_effect take?

level: middleimportance: must knowfreq 72%

basics

~20 s

side_effect accepts an exception class or instance to raise, an iterable that supplies one result per call, or a callable invoked with the same arguments the mock received. It takes priority over return_value unless the callable returns unittest.mock.DEFAULT.

open as a page

When does unittest.mock.patch install an AsyncMock instead of a MagicMock?

level: middleimportance: should knowfreq 50%

basics

~10 s

patch inspects the object it replaces: if it is a coroutine function, the replacement is an AsyncMock; anything else becomes a MagicMock. Passing new= or new_callable= switches that detection off entirely.

open as a page

What does Mock.assert_has_calls verify about the order and completeness of a mock's calls?

level: middleimportance: should knowfreq 38%

basics

~20 s

It checks that the expected calls appear in the mock's recorded calls as a consecutive run, in the order given. Extra calls before and after are allowed, so it never proves that nothing else happened.

open as a page

Why can a misspelled assertion on a unittest.mock Mock pass silently?

level: middleimportance: should knowfreq 44%

basics

~20 s

A Mock auto-creates any attribute you touch, so a misspelled assertion just returns a new child mock and checks nothing. CPython now rejects names that look like assertions, but forgetting the parentheses or typing the wrong attribute name still passes silently.

open as a page

How does unittest.mock.PropertyMock fake an attribute that is backed by a property?

level: middleimportance: should knowfreq 30%

basics

~20 s

PropertyMock implements the descriptor hooks, so it only works when attached to the class rather than to an instance. Reading the attribute calls it with no arguments; assigning to it calls it with the new value.

open as a page

In what order do stacked unittest.mock.patch decorators pass their mocks to a test?

level: middleimportance: should knowfreq 50%

basics

~10 s

Bottom-up: the decorator written closest to the def is applied first and supplies the first mock parameter, and the topmost decorator supplies the last. On a TestCase method the mocks follow self.

open as a page

How do you configure a unittest.mock.Mock's nested attributes in one call?

level: middleimportance: should knowfreq 35%

basics

~10 s

Pass dotted keyword arguments: Mock({'evaluate.return_value': True}) at construction, or mock.configure_mock({'close.side_effect': OSError}) afterwards. The constructor forwards its extra keyword arguments to configure_mock, so both forms do the same work.

open as a page

With unittest.mock, how do you double an `async with` resource and assert it was exited?

level: seniorimportance: should knowfreq 40%

basics

~20 s

MagicMock and AsyncMock already expose aenter and aexit as AsyncMocks, so set aenter.return_value to the fake resource and assert aexit was awaited. Match the factory's shape: a synchronous acquire() needs a MagicMock, an awaited one needs an AsyncMock.

open as a page

When does unittest.mock.create_autospec catch a bug that Mock(spec=...) misses?

level: seniorimportance: should knowfreq 40%

basics

~20 s

create_autospec rebuilds the target recursively and gives every callable its real signature, so a wrong number or name of arguments raises TypeError at the call. Mock(spec=...) checks attribute names only and leaves its children unconstrained.

open as a page

What do len() and iteration return on a MagicMock by default, and why is that dangerous in a test?

level: seniorimportance: should knowfreq 35%

basics

~20 s

A MagicMock is length zero and iterates as empty, while still being truthy. So a loop over one never executes and a test asserting on its results can pass while proving nothing — the classic vacuous green.

open as a page

A unittest.mock.patch started in setUp leaks into later tests; how do you guarantee the restore?

level: seniorimportance: should knowfreq 42%

basics

~10 s

Register the teardown at the moment you start the patch: call addCleanup(patcher.stop) right after patcher.start(). Cleanups run even when setUp raises partway, whereas tearDown is skipped entirely in that case.

open as a page

How do you use unittest.mock side_effect to test a retry path that times out twice then succeeds?

level: seniorimportance: should knowfreq 50%

basics

~20 s

Give the mocked call an iterable side_effect whose first entries are exception instances and whose last entry is the success value: two TimeoutError instances, then the payload. Each call consumes one entry, so the retry runs deterministically.

open as a page

Why does Mock.call_args_list show a mutated list rather than the value at call time?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

A mock records a reference to each argument, never a copy. If the code mutates or reuses that object after the call, the recorded call reflects the object's current state, so assertions compare against whatever it holds now.

open as a page