skip to content

Mock, MagicMock and Specs

What a Mock really is — an object that invents any attribute you touch — and how spec, spec_set and autospec pin it to a real interface. Unconstrained mocks accept calls production would reject.

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

questions

3

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

level: juniorimportance: must knowfreq 62%

answer

  1. Two mock classes, one real difference
  2. Ordinary attributes versus special methods
  3. Special methods are found on the type
  4. __len__ gives 0, __bool__ gives True
  5. MagicMock preconfigures the supported dunders

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.

solid answer

~50 s

`unittest.mock.Mock` invents any *ordinary* attribute the moment you touch it, but Python looks special methods up on the type rather than the instance, so a bare Mock has none: `len(Mock())` raises `TypeError` and using it in a `with` block fails the same way. `MagicMock` subclasses `Mock` and preconfigures the supported dunders with calculated defaults — `__len__` gives 0, `__bool__` gives True, `__iter__` gives an empty iterator, `__int__` gives 1, `__exit__` gives False — and each one is itself a mock you can reconfigure and assert on. A few are deliberately excluded, among them `__getattr__`, `__setattr__`, `__init__`, `__new__` and `__del__`, because faking them would break the mock machinery. `unittest.mock.patch` installs a `MagicMock` by default. The tradeoff is that those defaults make a double silently truthy and non-empty, so assertions about the shape of a mocked result can pass vacuously.

code

python · 11 lines
python
from unittest.mock import Mock, MagicMock

plain = Mock()
plain.charge(100)          # any ordinary attribute is invented on first touch
try:
    len(plain)             # ...but dunders are looked up on the type
except TypeError as exc:
    print(exc)             # object of type 'Mock' has no len()

magic = MagicMock()
print(len(magic), bool(magic), list(magic), int(magic))   # 0 True [] 1

go deeper

for a junior

Be ready to say the one-line difference out loud: MagicMock comes with the magic methods preconfigured, a plain Mock does not, so len() or a with block on a plain Mock raises TypeError. Knowing which class patch() gives you is a good bonus.

for a middle

Explain the mechanism, not just the fact: special methods are looked up on the type, so the attribute-inventing hook never runs for them, and MagicMock installs them on each mock's own throwaway subclass with calculated defaults.

for a senior

Show that you know what the defaults cost. An interviewer expects you to point out that truthiness and length assertions against a MagicMock are vacuous, and that the fix is a specced double plus assertions on calls rather than on invented return values.

for a principal

Own the convention. Decide whether your codebase defaults to autospecced doubles or bare MagicMocks, and be able to justify it in terms of which classes of interface drift the suite is meant to catch versus how much test boilerplate the team will tolerate.

## How a Mock manufactures attributes `unittest.mock.Mock` is an object with no interface of its own: it manufactures whatever you ask it for. The first time you touch `mock.charge`, the mock creates a child `Mock`, caches it, and returns it — so `mock.charge is mock.charge` holds and you can assert on that same child later. Calling it hands back yet another mock, its `return_value`. That is the whole trick, and it is why a Mock can stand in for almost anything with no configuration at all. ## The hole: implicit special-method lookup The trick has one hole, and the hole is in the language rather than in the library: **implicit special-method lookup bypasses the instance**. When you write `len(x)`, CPython does not look up `x.__len__` the way ordinary attribute access does; it consults `type(x)`. The attribute-inventing hook that gives a Mock its magic is never consulted, because syntax-driven protocol lookups never reach it. So: - `len(Mock())` raises `TypeError: object of type 'Mock' has no len()`, - using a plain Mock in a `with` block raises a TypeError about the context-manager protocol, - and `iter()`, `int()`, `+`, `[]` and `in` all fail the same way. ## What MagicMock configures `MagicMock` exists exactly to plug that hole. It subclasses `Mock` and, at construction, configures the *supported* magic methods, each as a child mock carrying a calculated default so that the result is a usable value rather than another mock: | Magic method | Default | |---|---| | `__len__` | 0 | | `__bool__` | True | | `__iter__` | an empty iterator | | `__int__` and `__index__` | 1 | | `__float__` | 1.0 | | `__contains__` | False | | `__exit__` | False | And `__str__`, `__hash__` and `__sizeof__` behave sensibly. The ordering methods return `NotImplemented`, which is why sorting two MagicMock objects still raises TypeError, and `__eq__` falls back to identity, so a MagicMock compares equal only to itself. A short list is deliberately excluded: `__getattr__`, `__setattr__`, `__init__`, `__new__`, `__instancecheck__`, `__subclasscheck__` and `__del__`. Faking those would break the mock machinery itself or make finalisation unpredictable, so they stay real. ## Why configuring the type affects one mock only How can the configuration live on the type when every mock is a separate object? Because every mock is given its own throwaway subclass at construction — `type(Mock()) is Mock` is False — so installing `__len__` on that type affects one mock only. This also means you can upgrade a plain Mock by hand: assigning `mock.__len__ = Mock(return_value=3)` is special-cased by the mock's own attribute-setting hook, which puts the callable on that private subclass, after which `len(mock)` returns 3. Assign one of the excluded names and you get `AttributeError: Attempting to set unsupported magic method '__getattr__'.` ## The variants you will meet Which class do you actually get in practice? - `unittest.mock.patch` and `unittest.mock.create_autospec` build a `MagicMock` by default. - `AsyncMock`, added in 3.8, is chosen automatically when the object being replaced is a coroutine function, so awaiting the double does not blow up. - `NonCallableMock` and `NonCallableMagicMock` are the variants used where the specced object is not callable — for instance the instance-shaped mock that an autospecced class returns when you call it. ## The cost of generosity The practical cost of MagicMock's generosity is that assertions about its defaults are vacuous. `assert result` passes for any MagicMock. `assert len(rows) == 0` passes and `assert not rows` fails on the *same* mock, for reasons that have nothing to do with the code under test. A test claiming "the job produced no entries" that asserts emptiness against a MagicMock return value is asserting a library default, not a behaviour. The remedy is not to avoid MagicMock — you usually want the dunders — but to pin the double to a real interface with `spec=` or `unittest.mock.create_autospec`, and to assert on the *calls* the code made rather than on the shape of an invented return value. One consequence worth internalising: because MagicMock's dunder children are themselves mocks, they are recorded like any other call. If the code under test iterates the double or takes its length, that shows up in the mock's call record, so you can assert that the collaborator was iterated at all. That is occasionally the cleanest way to prove the code walked a result set rather than indexing it, and it is a capability a plain Mock cannot offer because the operation raises before it can be recorded. ## A workable rule - Reach for `MagicMock` (or simply let `patch` hand you one) when the double stands in for something used with syntax — a context manager, something iterated, something indexed or tested with `in`. - Reach for a plain `Mock` when you want the double to fail loudly the moment the code under test starts treating it as a container or a context manager, which is a small but real form of interface checking. - When you know the interface, prefer a specced mock over either, and let the spec rather than the class do the constraining.

  • Can you give a plain Mock a working __len__ by assigning to it?
    Yes. Every mock is constructed with its own throwaway subclass, and the mock's attribute-setting hook special-cases the supported magic methods by installing them on that subclass, so `mock.__len__ = Mock(return_value=3)` makes `len(mock)` return 3. Assigning an excluded name such as `__getattr__` raises AttributeError with a message about an unsupported magic method. MagicMock simply does this for the whole supported set up front.
  • Why can comparing or sorting two MagicMock objects still fail?
    MagicMock's ordering methods default to `NotImplemented`, so sorting a list of two MagicMock objects raises TypeError about `<` not being supported. Equality defaults to identity, so a MagicMock equals itself and nothing else. If a test needs ordering or value equality, configure `__lt__` or `__eq__` explicitly, or better, use a real value object instead of a double.
  • When is a plain Mock actually the better choice?
    When you want the double to fail loudly if the code under test starts treating it as a container, an iterable or a context manager. MagicMock's defaults absorb that misuse silently; a plain Mock raises TypeError and tells you the code is doing something the double was never meant to support. It is a crude but genuine interface check.

A Mock is a shop assistant who says yes to anything you ask out loud; the dunders are the things Python reads off the shelf label instead of asking, and only MagicMock bothers to print a label.

saying these in an interview costs you the question

  • Thinks MagicMock is just a friendlier alias for Mock
  • Says a plain Mock supports every method, dunders included
  • Believes MagicMock is constrained to a real interface by default
  • Assumes a mocked return value is falsy or empty by default
  • Claims patch() installs a plain Mock by default
  • Believes special methods are looked up on the instance

context

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

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