skip to content

Verification Modes & Ordering

Beyond a plain verify you can assert exact counts, ranges, ordering, or a strict sequence, and confirmVerified checks you left nothing unasserted. Choosing the weakest verification that still proves your point is the judgment being tested.

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

questions

5

In MockK, how do you assert that a mocked method was called a specific number of times, and what does verify { ... } default to when you don't pass a count?

level: juniorimportance: must knowfreq 70%

answer

  1. exactly = n is a named param outside the lambda
  2. bare verify = atLeast = 1 (not exactly once)
  3. exactly = 0 means never called
  4. no verifyNever API exists
  5. count is over matching invocations

basics

~20 s

Use verify(exactly = n) { mock.method() } to require exactly n calls. A plain verify { ... } with no count means "at least one call" (atLeast = 1), so it fails only if the call never happened.

solid answer

~40 s

MockK's verify takes named parameters that control the count. verify(exactly = n) { mock.foo() } asserts the matching call happened exactly n times; verify(exactly = 0) { mock.foo() } asserts it never happened (a negative assertion). A bare verify { mock.foo() } defaults to atLeast = 1, i.e. one or more calls. The lambda body uses the same argument matchers (any(), eq(), capturing slots) as every. Counts apply per matching invocation, so verify(exactly = 2) { mock.foo(any()) } passes only when foo was invoked twice with any argument. Use exactly = 0 instead of a separate "never called" API — MockK has no verifyNever; the count expresses it.

code

kotlin · 6 lines
kotlin
val repo = mockk<Repo>(relaxed = true)
service.process(order)

verify(exactly = 1) { repo.save(order) }   // precisely once
verify(exactly = 0) { repo.delete(any()) } // never
verify { repo.audit(any()) }               // at least once (default)

go deeper

for a junior

Knows verify(exactly = n) and that exactly = 0 means never called.

for a middle

Knows the bare-verify default is atLeast = 1 and that counts are over matching invocations only.

for a senior

Explains why there is no verifyNever and how matchers in the lambda affect what gets counted.

for a principal

Frames exactly vs atLeast/atMost as a deliberate API design and advises teams when exact counts make tests brittle vs precise.

## What `verify` does `verify` is MockK's assertion that recorded calls on a **mock** (a fake object whose behavior you stubbed with `every`) actually occurred. It does **not** stub anything; it checks history after the code under test ran. ## The `exactly` parameter The count is passed as a **named argument** to `verify`, not inside the lambda: ```kotlin val repo = mockk<Repo>(relaxed = true) service.save(item) verify(exactly = 1) { repo.insert(item) } // exactly one call verify(exactly = 0) { repo.delete(any()) } // never called (negative) verify(exactly = 3) { repo.touch() } // precisely three ``` - `exactly = 0` is the idiomatic **"never happened"** assertion. MockK has **no** `verifyNever`; you express it with the count. - The lambda holds the **call expectation** with argument matchers: `any()`, `eq(x)` (the default for literals), `range(...)`, or a capturing `slot()`. ## Default when no count is given A bare `verify { repo.insert(item) }` is equivalent to `verify(atLeast = 1)` — it passes if the call occurred **one or more** times and fails only when it never occurred. So an unparameterised `verify` is **not** an exact-once check; if you need exactly-once, write `exactly = 1`. ## Counting semantics The count is over **invocations matching the lambda**. `verify(exactly = 2) { repo.find(any()) }` requires two calls to `find` with any argument. If `find` was called twice but with arguments that don't match your matcher, those calls don't count. ## Relation to other modes `exactly` is one of several count modes; the others are `atLeast`, `atMost`, and a `timeout`. They are mutually meaningful named params on the same `verify` overload.

  • How do you assert a call never happened?
    verify(exactly = 0) { mock.method(...) }. There is no verifyNever; the zero count is the negative assertion.
  • Does verify(exactly = 1) check the order relative to other calls?
    No. exactly only counts matching invocations of that one expectation. Ordering across calls needs verifyOrder or verifySequence.

Like checking a doorbell log: exactly = 3 says the bell rang precisely three times, exactly = 0 says it never rang.

saying these in an interview costs you the question

  • Thinking a bare verify { } means 'called exactly once'
  • Inventing a verifyNever() function
  • Putting the count inside the lambda instead of as a named param
  • Confusing exactly = 0 with confirmVerified

context

open as a page

What is the difference between verifyOrder and verifySequence in MockK? When would each fail given a stream of recorded calls?

level: middleimportance: must knowfreq 60%

basics

~20 s

verifyOrder checks that the listed calls happened in that relative order, allowing other calls in between or around them. verifySequence is stricter: the listed calls must be the complete, exact, back-to-back list of all calls on those mocks, with nothing else.

open as a page

Explain verify(atLeast = n), verify(atMost = n), and how to assert a call count falls within a range in MockK. What happens if a verified call occurs more times than atMost allows?

level: middleimportance: should knowfreq 55%

basics

~20 s

atLeast = n requires n or more calls; atMost = n allows up to n. Combine them in one verify to assert a range. If calls exceed atMost, verification fails because too many matching invocations were recorded.

open as a page

What do confirmVerified and excludeRecords do in MockK, and how do they combine to assert that no unexpected interactions occurred on a mock?

level: seniorimportance: should knowfreq 40%

basics

~20 s

confirmVerified(mock) asserts every recorded call on that mock was already verified — failing if any call went unchecked. excludeRecords removes uninteresting calls from the mock's recorded history so they don't trip confirmVerified or sequence checks.

open as a page

Your team's interaction tests using verifySequence and confirmVerified keep breaking on benign refactors. How would you diagnose this and rework the verification strategy while keeping meaningful coverage?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

Over-strict verifiers couple tests to incidental call order and noise. Reserve verifySequence/confirmVerified for true protocols; elsewhere use verify with counts or verifyOrder for the calls that matter, and excludeRecords to drop noise. Prefer state assertions over interaction assertions when possible.

open as a page