What does Mock.assert_has_calls verify about the order and completeness of a mock's calls?
answer
- It is a subsequence check, not equality
- Extra calls around the run are tolerated
- The expected calls must sit next to each other
- any_order drops the ordering requirement
- mock_calls entries carry the attribute name
basics
~20 sIt 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.
solid answer
~40 s`assert_has_calls([...])` takes a list of `call` objects and asserts that the mock's `mock_calls` contains that sequence **contiguously and in order**. Calls before and after the run are ignored, so it is a subsequence check, not an equality check — it can never assert "and nothing else". Passing `any_order=True` relaxes it to "each expected call appears somewhere", dropping the ordering requirement. Two details bite: `mock_calls` on a parent records name-qualified entries such as `call.emit("KJ118")`, so a bare `call("KJ118")` will not match there; and `mock_calls` also records calls made to a mock's return value, which `call_args_list` does not. When the contract really is an exact interaction, compare the record directly: `assert mock.mock_calls == [call.emit(1), call.emit(2)]`.
code
python · 18 linesfrom unittest.mock import Mock, call, ANY
sink = Mock()
for flight in ("KJ118", "KJ204", "KJ377"):
sink.emit(flight, at=object())
sink.emit.assert_has_calls([call("KJ204", at=ANY), call("KJ377", at=ANY)])
print("consecutive run ok")
try:
sink.emit.assert_has_calls([call("KJ118", at=ANY), call("KJ377", at=ANY)])
except AssertionError as exc:
print("non-consecutive fails:", str(exc).splitlines()[0])
sink.emit.assert_has_calls(
[call("KJ377", at=ANY), call("KJ118", at=ANY)], any_order=True
)
print("any_order ok")go deeper
Know that it takes a list of call objects and checks the mock saw them in that order. Remember that other calls around them are allowed, so a pass does not mean nothing else happened.
Explain the mechanics: a contiguous, ordered subsequence of mock_calls, relaxed by any_order=True, with each call compared using ==. Know that mock_calls entries are name-qualified and include return-value calls.
Show judgment on when order belongs in an assertion at all, and reach for a call_args_list equality comparison when the contract is an exact interaction rather than a partial one.
Own the tradeoff between interaction assertions and outcome assertions: ordered call checks couple tests to implementation, and you decide where that coupling is worth its refactoring cost.
`assert_has_calls` is the assertion for "these interactions happened, in this order". It is easy to over-read, because what it actually guarantees is narrower than most people assume. ## The check it performs You hand it a list of `unittest.mock.call` objects. It looks at the mock's `mock_calls` list and passes if your list appears there as a **contiguous run, in the same order**. Anything recorded before that run and anything after it is ignored. So on a mock that received `emit("KJ118")`, `emit("KJ204")`, `emit("KJ377")`: * `[call("KJ204"), call("KJ377")]` passes — a consecutive run at the end. * `[call("KJ118"), call("KJ377")]` fails — those two are real calls, but not adjacent. * `[call("KJ377"), call("KJ118")]` fails — wrong order. Passing `any_order=True` changes the check to "every expected call is present somewhere", discarding both adjacency and order; duplicates in your expected list still require that many matching recorded calls, because each match is consumed as it is found. Duplicates matter in the ordered form too. Expecting `[call(1), call(1)]` demands two adjacent identical calls, not one call that happens to match twice, so the assertion does carry information about repetition even though it carries none about what surrounds the run. And note which mock you call it on: `child.assert_has_calls(...)` searches that child's record, while `parent.assert_has_calls(...)` searches the parent's, where the entries look different. ## What it can never tell you Because the check ignores surrounding calls, `assert_has_calls` cannot express completeness. A mock that also fired three unexpected calls in between passes just as happily, provided your run is intact. If the contract you are testing is "exactly these calls and nothing else", assert on the record itself: ```python assert sink.emit.call_args_list == [call("KJ118"), call("KJ204")] ``` or, for a parent whose children were exercised, `assert sink.mock_calls == [call.emit("KJ118"), call.emit("KJ204")]`. List equality checks the count, the order and the arguments in one comparison, and its failure message shows you both sides. ## mock_calls versus call_args_list These two records are not the same list, and `assert_has_calls` uses `mock_calls`. * `child.call_args_list` holds only the direct calls to that mock, as bare `call(...)` entries. * `parent.mock_calls` holds calls to the parent, to its auto-created children, **and to their return values**, with each entry qualified by the attribute path. Calling `sink.emit("KJ118").ack()` records `call.emit("KJ118")` and `call.emit().ack()` on `sink`. Two consequences follow. First, when you assert on a parent you must build name-qualified expectations — `call.emit("KJ118")`, not `call("KJ118")` — and the `call` helper supports that with attribute access precisely so you can write the chain out. Second, a mock's `mock_calls` can be longer than you expected because the return-value interactions are in there too, which is a common source of a puzzling `assert_has_calls` failure on a fluent API. ## Matching individual arguments Each expected `call` is compared to a recorded one with `==`, argument by argument. Where an argument is unpredictable — a generated identifier, a timestamp, an object with no useful equality — use `unittest.mock.ANY`, a sentinel that compares equal to anything. It is deliberately placed on the left of the comparison inside mock so that its `__eq__` wins over the other object's, which is why it works even against types with a strict `__eq__`. Use it surgically: `call("KJ118", at=ANY)` still pins the flight identifier, whereas replacing the whole call with `ANY` asserts nothing. ## Choosing an assertion * One interaction, and repeats would be a bug: `assert_called_once_with`. * One interaction among many, order irrelevant: `assert_any_call`. * An ordered sequence that is part of the contract, with other traffic allowed around it: `assert_has_calls`. * The complete interaction, nothing else permitted: compare `call_args_list` or `mock_calls` for equality. The ordering question is worth a moment's thought before you reach for `assert_has_calls` at all. If the code under test is genuinely free to reorder those calls, asserting the order pins an implementation detail and produces a test that fails on a harmless refactor; `any_order=True` or a set-style comparison says what you actually meant. If the order is the contract — open before write, write before close, a batch flushed before the connection is torn down — then the ordered form is the one carrying real information, and it is worth the coupling.
- How do you assert that a mock received exactly the calls you list and no others?Not with `assert_has_calls`, which ignores surrounding calls. Compare the record for equality instead: `assert mock.call_args_list == [call(1), call(2)]` for a single mock, or `assert parent.mock_calls == [call.emit(1), call.emit(2)]` when children were exercised. That one comparison pins the count, the order and the arguments together.
- Why does a bare call("KJ118") fail to match an entry in a parent mock's mock_calls?Entries in `mock_calls` on a parent are name-qualified: calling `sink.emit("KJ118")` records `call.emit("KJ118")`, and that does not equal `call("KJ118")`. Build the expectation with the same attribute path using the `call` helper's attribute access, or assert on the child mock's own `call_args_list`, whose entries are unqualified.
- What is unittest.mock.ANY for, and where does it belong in an expected call?`ANY` is a sentinel that compares equal to any object, for arguments you cannot predict such as generated identifiers or timestamps. Mock arranges the comparison so `ANY.__eq__` wins over the other operand's. Use it for the single unpredictable argument, keeping the rest of the call pinned; replacing the entire expected call with `ANY` turns the assertion into a no-op.
saying these in an interview costs you the question
- Thinks assert_has_calls proves no other calls happened
- Assumes the expected calls may be scattered non-consecutively
- Believes any_order=True also allows missing calls
- Confuses mock_calls with call_args_list on a parent mock
- Writes bare call() expectations against a parent's mock_calls
- Asserts call order on code that is free to reorder the calls