skip to content

How do you verify with MockK that a method was (or was not) called, and how many times?

level: middleimportance: must knowfreq 80%

answer

  1. verify { } = did the call happen
  2. exactly / atLeast / atMost counts
  3. exactly = 0 = never called
  4. mock wasNot Called = no interactions
  5. confirmVerified = nothing left unchecked

basics

~20 s

Use verify { mock.method(args) } after the action to check the call happened. You can also pass exactly = n, atLeast, atMost, or exactly = 0 to assert how many times it ran or that it never ran.

solid answer

~40 s

verify { } asserts that a recorded interaction occurred on a mock. The lambda describes the expected call, exactly like every does. Count parameters control multiplicity: verify(exactly = 1) { mock.foo() }, verify(atLeast = 2), verify(atMost = 3), and verify(exactly = 0) to assert a call never happened. To prove a mock got no calls at all, use verify { mock wasNot Called }. confirmVerified(mock) fails the test if any interaction was left unverified, catching unexpected calls. Argument matching in verify uses the same matchers as stubbing — any(), eq(), and capture(). Verification ignores the order of calls unless you use ordering variants (a sibling topic). A common mistake is verifying a call that was never stubbed on a strict mock — the action under test would have thrown before reaching verify.

code

kotlin · 6 lines
kotlin
val repo = mockk<UserRepository>(relaxed = true)
UserService(repo).register("Ada")

verify(exactly = 1) { repo.save(any()) }
verify(exactly = 0) { repo.delete(any()) }
confirmVerified(repo)

go deeper

for a junior

Can write a plain verify { } that a method was called.

for a middle

Uses exactly/atLeast/atMost counts and exactly = 0 for never-called; knows verify uses the same matcher DSL.

for a senior

Adds confirmVerified and wasNot Called, and explains why a strict mock can defeat verify.

for a principal

Discusses verification discipline as a design signal — over-verifying couples tests to implementation; verifies behaviour, not every interaction.

## Purpose of verification Stubbing (`every`) sets up *inputs*; verification (`verify`) checks *outputs* — the side-effecting calls your code made on its collaborators. It answers 'did my service actually call `repo.save(...)`?'. ## Basic verify ```kotlin val repo = mockk<UserRepository>(relaxed = true) val service = UserService(repo) service.register("Ada") verify { repo.save(any()) } // fails if save was never called ``` The lambda inside `verify { }` is the same recording DSL as `every`: you write the call you expect to have happened. ## Counting calls `verify` accepts named count parameters: - `verify(exactly = 1) { repo.save(any()) }` — called exactly once. - `verify(exactly = 0) { repo.delete(any()) }` — **never** called. - `verify(atLeast = 2) { ... }` — at least twice. - `verify(atMost = 3) { ... }` — at most three times. - combine: `verify(atLeast = 1, atMost = 3) { ... }`. ## Asserting no interactions ```kotlin verify { repo wasNot Called } // this mock received no calls at all ``` ## Confirming everything was checked `confirmVerified(repo)` fails if the mock had interactions you didn't `verify`. It guards against silent, unexpected calls: ```kotlin verify { repo.save(any()) } confirmVerified(repo) // fails if repo got other calls too ``` ## Matchers in verify You can be loose or exact about arguments: ```kotlin verify { repo.findById(eq(1L)) } // exact verify { repo.findById(any()) } // any argument ``` `any()`, `eq()`, and `capture(slot)` work identically in `every` and `verify`. ## Order vs. count Plain `verify` does not care about ordering or about other calls happening in between. Strict ordering (`verifyOrder`, `verifySequence`) is a separate verification-modes topic. ## Common pitfalls - On a **strict** mock, the code under test throws on the first unstubbed call, so you never reach `verify`. Either stub the call or use `relaxed = true`. - `verify(exactly = 0)` is the right way to assert 'never called' — not wrapping a missing call in a try/catch. - Forgetting `confirmVerified` lets unexpected extra calls slip through.

  • How do you assert that a mock was never touched at all?
    verify { mock wasNot Called } — it fails if the mock received any interaction.
  • What does confirmVerified add over plain verify?
    It fails the test if the mock had any interactions you didn't explicitly verify, catching unexpected extra calls.

saying these in an interview costs you the question

  • Using verify to set up return values (that's every)
  • Asserting 'never called' with try/catch instead of exactly = 0
  • Verifying a call on a strict mock that the code throws on before reaching verify
  • Assuming plain verify checks call order
  • Never using confirmVerified and missing unexpected calls

context