How do you configure a unittest.mock.Mock's nested attributes in one call?
answer
- Compressing several setup lines into one
- Keyword names carrying dots
- Dictionary unpacking is mandatory here
- Shallow keys applied before deeper ones
- One keyword the constructor steals
basics
~10 sPass 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.
solid answer
~40 s`Mock(**kwargs)` hands its surplus keyword arguments straight to `configure_mock`, and both understand *dotted* keys: `Mock(**{"evaluate.return_value": True, "close.side_effect": OSError})` walks the attribute chain, auto-creating each child mock, and sets the final attribute. That collapses several setup lines into one statement, which is why it is the idiomatic way to configure a double at construction time. Keys are applied fewest-dots-first, so a shallow assignment can never clobber a deeper one made in the same call. The trap is `name`: it is a genuine parameter of the `Mock` constructor used for the mock's repr, so `Mock(name="flags-client")` names the mock rather than setting an attribute — reading `.name` still gives an auto-created child. Use `configure_mock(name=...)`, or plain assignment, when you need an attribute called `name`.
code
python · 11 linesfrom unittest.mock import Mock
client = Mock(**{
"evaluate.return_value": {"enabled": True},
"close.side_effect": OSError("socket already closed"),
})
print(client.evaluate("beta-banner"))
try:
client.close()
except OSError as exc:
print("raised:", exc)go deeper
Know that a mock can be configured at construction with keyword arguments, and that a dotted key like 'evaluate.return_value' has to be passed through dictionary unpacking.
Explain that the constructor forwards surplus kwargs to configure_mock, that dotted keys walk and auto-create child mocks, and why the name keyword configures the mock's repr instead of an attribute.
Show that you use the compressed form to keep arrange blocks readable and table-driven, and that you recognise a deep dotted key as a test coupling itself to a dependency's internals.
Own the convention. Decide how deep the team's doubles may be configured before a shared in-memory fake replaces them, since chained configuration is the mechanism by which one dependency refactor breaks a hundred unrelated tests.
Configuring a test double one line at a time gets verbose quickly: a client with two methods, one of which returns an object with its own attributes, is four or five statements of setup before the test does anything. `configure_mock` and the `Mock` constructor's keyword arguments exist to compress that. ### Dotted keys walk the attribute chain Both accept keyword arguments whose *names* may contain dots: ```python client = Mock(**{ "evaluate.return_value": {"enabled": True}, "close.side_effect": OSError("socket already closed"), }) ``` For each key, the implementation splits on `.`, pops the final segment, walks the remaining segments with `getattr` — auto-creating child mocks as it goes — and calls `setattr` for the last one. So `"evaluate.return_value"` resolves the child `client.evaluate` and sets `return_value` on it. Depth is unlimited: `"session.get.return_value.status"` is a perfectly valid key. Note that the `**{...}` unpacking is not decorative — `Mock(evaluate.return_value=1)` is a syntax error, because a keyword argument name must be an identifier. Dictionary unpacking is the only way to smuggle a dotted name in. The constructor is not a separate mechanism: any keyword argument it does not recognise as one of its own parameters is forwarded to `configure_mock`. Anything you can do at construction you can also do later on an existing mock, which matters when a fixture creates the double and individual tests refine it. ### Application order is deliberate `configure_mock` sorts its keys by the number of dots and applies the shallowest first. The reason is subtle but important: setting `"evaluate.return_value"` *replaces* the object that `client.evaluate()` returns, so if the deeper key `"evaluate.return_value.status"` had been applied first, its work would be discarded. Shallow-first means both keys in one call compose correctly. Relying on that is fine; relying on the order of *equally deep* keys is not, since it falls back to alphabetical sorting of the key names. ### The name collision The one real trap is `name`. `Mock` takes `name` as an actual constructor parameter and uses it for the mock's `repr`, which is genuinely useful when a failure message would otherwise show three indistinguishable mocks. So `Mock(name="flags-client")` does not create an attribute; reading `.name` afterwards still returns an auto-created child mock, and an assertion comparing it to a string fails with a confusing message. The workarounds are to configure it after construction — `mock.configure_mock(name="flags-client")`, which goes through plain `setattr` — or simply `mock.name = "flags-client"`. The same shadowing applies to every other real parameter of the constructor: `spec`, `spec_set`, `side_effect`, `return_value`, `wraps` and `parent` are consumed by `Mock` itself, so an object under test whose attribute is genuinely called `wraps` or `spec` cannot have it configured through constructor kwargs either. The rule to remember is that constructor keywords are *shared* between mock configuration and attribute configuration, and mock configuration wins. ### When to reach for it, and when not to The compressed form pays for itself when a double needs three or more settings, or when the double is created inside a helper that receives its configuration as a dict — a table-driven test can then carry a `{"evaluate.return_value": ...}` mapping per case and build the double from it. It also keeps arrange blocks readable: one statement that visibly describes the whole collaborator beats five scattered assignments. It does not change any semantics. A dotted key is exactly equivalent to the assignments it performs, so everything about `return_value` and `side_effect` still applies: the value comes back by identity, an exception assigned to `side_effect` is raised, an iterable is consumed once. The honest caution is the same one that applies to long attribute chains generally. A key like `"session.get.return_value.json.return_value"` encodes four assumptions about a collaborator's internals into a test that is nominally about your own code. When those chains multiply across a suite, a small refactor in the dependency breaks dozens of tests that never meant to depend on it. At that depth a hand-written fake, or a narrower interface between your code and the dependency, is usually the better answer — the compression is a convenience, not a licence to reach deeper. All of this behaves identically across Python 3.10–3.14. ### Mixing constructor parameters with dotted keys Because the constructor's own parameters and the forwarded configuration keys share one keyword namespace, a single call can do both jobs: `Mock(return_value=3, **{"evaluate.side_effect": KeyError})` configures the mock's own result *and* a child's behaviour. Read that call carefully — the bare `return_value` belongs to `client()` while the dotted key belongs to `client.evaluate()`, and confusing the two is the same mistake as setting `return_value` on the parent instead of the called child. When a setup line starts mixing both in a way that needs a second read, splitting it into named statements is worth more than the compression.
- Why does configure_mock apply its keys fewest-dots-first?Because a shallower assignment replaces the object a deeper one was configured on. Setting `"evaluate.return_value"` swaps out what `evaluate()` returns, so if `"evaluate.return_value.status"` had been applied first its work would vanish. Sorting by dot count guarantees parents are set before children, letting both keys appear in a single call.
- Which other keyword names does the Mock constructor consume before they reach attribute configuration?Its own parameters: `spec`, `spec_set`, `side_effect`, `return_value`, `wraps`, `parent` and `name`. Any of those in the constructor call configures the mock itself rather than creating an attribute of that name, so a collaborator with an attribute genuinely called `wraps` or `name` must be configured afterwards with `configure_mock` or plain assignment.
- When is a long dotted configuration key a smell rather than a convenience?When the chain describes the dependency's internals rather than your seam with it. A key like `"session.get.return_value.json.return_value"` bakes four structural assumptions into a test about your own code, so an unrelated refactor in the dependency breaks it. At that depth a small hand-written fake, or a narrower interface, ages far better.
saying these in an interview costs you the question
- Thinks Mock(name='x') sets a name attribute
- Writes Mock(evaluate.return_value=1) without dictionary unpacking
- Believes configure_mock discards earlier configuration
- Assumes deeper keys are applied before shallower ones
- Expects Mock(spec=...) to create an attribute called spec