skip to content

MockK offers verifyAll alongside verifyOrder and verifySequence. What does verifyAll assert that a plain verify does not, which calls fall inside its scope, and how does its failure condition differ from verifySequence's?

level: middleimportance: should knowfreq 35%

answer

  1. two axes: completeness × order
  2. verifyAll = exhaustive, order-free
  3. verifySequence = exhaustive + exact order
  4. exhaustive only over mocks named in the block
  5. matchers widen what an entry covers

basics

~20 s

verifyAll is exhaustive but order-free: every call you list must have happened, and every recorded call on the mocks named in the block must be matched by some entry. verifySequence adds the requirement that the order match exactly.

solid answer

~50 s

All four MockK verification functions are the same query with a different success criterion — they map onto the `Ordering` values `UNORDERED`, `ALL`, `ORDERED` and `SEQUENCE`. Plain `verify` is a pure existence check: the listed calls happened, everything else is ignored. `verifyAll` adds **exhaustiveness**: on top of "these happened", every recorded call on the mocks referenced in the block must be covered by one of the entries. Order is irrelevant. So `verifyAll` fails when an interaction you did not mention occurred — it is the mode that says "these calls and nothing else". `verifySequence` is exhaustive *and* ordered: same completeness requirement, plus the recorded calls must appear in exactly the listed order, one-to-one. It therefore fails for a superset of reasons. Scope matters: exhaustiveness applies to the mocks you reference inside the block, not to every mock in the test. Calls on a collaborator you never mention do not break `verifyAll`.

code

kotlin · 11 lines
kotlin
service.handle(cmd) // repo.save(x), repo.findById(1), metrics.increment("saved")

verifyAll {
    repo.findById(1)   // order irrelevant
    repo.save(x)
}                       // passes: metrics never referenced here

verifySequence {
    repo.findById(1)
    repo.save(x)
}                       // fails: recorded order was save, then findById

go deeper

for a junior

State the headline: verifyAll means these calls and no others, order irrelevant; verifySequence additionally fixes the order.

for a middle

Lay out the two axes and place all four functions on them, and mention that exhaustiveness covers only the mocks named in the block.

for a senior

Add that matchers determine coverage, that counts are a separate assertion, and explain why relaxed mocks and exhaustive modes fight each other.

for a principal

Talk about when a complete interaction is genuinely the contract — narrow ports, protocol-shaped collaborators — and why exhaustive modes are a deliberate, scoped choice rather than a default.

## One engine, four success criteria MockK records each invocation on a mock into a chronological call record. Every verification function queries that record; they differ only in what counts as success. `verifyOrder` is shorthand for `verify(ordering = Ordering.ORDERED)`, and the family maps onto the four `Ordering` values: | Function | Ordering | Listed calls must have happened | Unlisted calls allowed | Order enforced | |---|---|---|---|---| | `verify` | `UNORDERED` | yes | yes | no | | `verifyAll` | `ALL` | yes | **no** | no | | `verifyOrder` | `ORDERED` | yes | yes | relative | | `verifySequence` | `SEQUENCE` | yes | **no** | exact | Read down the "unlisted calls allowed" column and the design becomes obvious: `ALL` and `SEQUENCE` are the *exhaustive* pair, `UNORDERED` and `ORDERED` are the *tolerant* pair. Read across and you see the second axis: ordering. `verifyAll` is the mode people forget, and it is exactly the one you want when completeness matters but order does not. ## What exhaustiveness means concretely Suppose the code calls `repo.save(x)`, `repo.findById(1)` and `metrics.increment("saved")`. ```kotlin verifyAll { repo.findById(1) repo.save(x) } ``` This passes. Order is irrelevant, so listing `findById` first is fine. And `metrics.increment` does not break it, because `metrics` is never referenced inside the block — exhaustiveness is scoped to the mocks that appear in the block, not to the test as a whole. Now add one more call on `repo`, say `repo.flush()`. The same block now fails: `repo` has a recorded call that no entry covers. That is the whole value proposition — it turns "the collaborator was used at least this much" into "the collaborator was used exactly this much". ## How it differs from verifySequence's failure condition Swap `verifyAll` for `verifySequence` in the block above and it fails immediately, because `findById` was listed before `save` but happened after. `verifySequence` requires a one-to-one, position-by-position match with the recorded calls of the referenced mocks. Every failure of `verifyAll` is also a failure of `verifySequence`; the converse is not true. In practice: - Use `verifyAll` when the *set* of interactions is the contract ("this handler touches the repository exactly twice, and I do not care in which order the two reads happen"). - Use `verifySequence` only when the *protocol* is the contract (`begin`, `write`, `commit`; or a builder that must be configured before `build()`). ## Matchers widen coverage Exhaustiveness is evaluated through your matchers, not through literal equality of your intent. `verifyAll { repo.save(any()) }` covers *every* recorded `save` call regardless of argument, so three saves are all matched by that single entry and the block still passes. If you want "exactly one save", the count belongs in a separate `verify(exactly = 1)` — the ordering functions accept no count parameters, only `inverse`. ## The relaxed-mock trap Exhaustive modes and relaxed mocks pull in opposite directions. A relaxed mock happily answers calls you never thought about — an id getter, a `size`, an accessor used inside a log statement — and each of those is a recorded call that `verifyAll` will demand you cover. Teams that lean on relaxed mocks for convenience usually find exhaustive verification too noisy on wide interfaces, and reserve it for narrow, deliberately-designed ports. ## Relation to the after-the-fact form MockK also offers `confirmVerified(mock)`, which asserts after your ordinary `verify` calls that nothing is left unverified. `verifyAll` reaches the same end state in a single block. The practical difference is style: `verifyAll` states the complete interaction in one place, while `confirmVerified` lets you build the picture out of several focused `verify` calls and then close the door. Both stand on the same recorded-call bookkeeping. ## Suspend variants `coVerifyAll`, `coVerifyOrder` and `coVerifySequence` are the suspend-capable twins, with identical semantics; only the ability to call suspend members inside the block differs. ## What to say in an interview Name the two axes — completeness and order — place the four functions on them, then say which failures each mode produces. That framing answers "why does my test break when I add a log call?" before it is even asked.

  • If verifyAll is exhaustive, does a call on a completely different mock make it fail?
    No. Exhaustiveness is scoped to the mocks referenced inside the block. If the block only mentions `repo`, MockK checks `repo`'s recorded calls for full coverage and ignores every other mock in the test. To make a second collaborator exhaustive too, you must mention it in the block.
  • You wrote verifyAll { repo.save(any()) } and three saves happened. Does it pass?
    Yes. Coverage is decided through matchers: the single entry with `any()` matches all three recorded saves, so nothing is left uncovered and the block passes. Exhaustive modes do not imply a count of one — if the count is part of the contract, assert it separately with `verify(exactly = 1) { repo.save(any()) }`.

saying these in an interview costs you the question

  • Thinking verifyAll checks order — it is the order-free exhaustive mode
  • Believing verifyAll makes every mock in the test exhaustive rather than the ones named in the block
  • Assuming one listed entry with any() means "exactly one call"
  • Treating verifyAll and verifySequence as interchangeable strictness levels without naming the order axis
  • Reaching for exhaustive modes on wide relaxed mocks and then blaming MockK for flaky failures

context