skip to content

Beyond asserting an exact call count, what verification modes does Mockito offer for expressing 'not at all', 'at least n times' and 'at most n times', and when would you prefer each?

level: middleimportance: should knowfreq 58%

answer

  1. never() == times(0), nicer message
  2. atLeastOnce()/atLeast(n) = lower bound
  3. atMost(n) = upper bound, zero passes
  4. never/atMost unsupported in InOrder
  5. count = spec -> times(n); artefact -> bound

basics

~20 s

never() asserts zero matching calls (same as times(0)). atLeastOnce() and atLeast(n) assert a lower bound; atMost(n) asserts an upper bound. Use bounds when the exact count is an implementation detail - retries, caching, loops - and exact times(n) when the count is the contract.

solid answer

~50 s

All of these are `VerificationMode` values passed as the second argument to `verify`. - `never()` - zero matching invocations; identical to `times(0)` but reads better and produces a clearer failure. - `atLeastOnce()` / `atLeast(n)` - a lower bound; more calls are fine. - `atMost(n)` - an upper bound; fewer calls are fine, including zero. Choose by asking whether the count is part of the behaviour you are specifying. "The circuit breaker must not call the downstream client after opening" is `never()`. "The cache must hit the loader no more than once for repeated reads" is `atMost(1)` or exact `times(1)`. "The retry policy calls at least twice" is `atLeast(2)` when the upper bound is genuinely unconstrained. A caution: `atMost` and `never` cannot be used in `InOrder` verification, and loose bounds weaken a test - `atLeastOnce()` on everything hides duplicate work that exact counts would catch.

code

java · 8 lines
java
@Test
void retriesButNeverNotifiesOnSuccess() {
    service.processWithRetry(order);

    verify(client, atLeast(2)).send(order);        // lower bound: retries
    verify(client, atMost(5)).send(order);         // upper bound: retry cap
    verify(alerting, never()).pageOnCall(any());   // must not happen at all
}

go deeper

for a junior

Recall the four modes and what each asserts; know never() means zero matching calls.

for a middle

Explain that these are VerificationMode strategies over the matching invocations, that never() equals times(0), and give one concrete case for each bound.

for a senior

Lead with the decision rule - is the count contractual or incidental - and call out that blanket lower bounds hide duplicate-work regressions.

for a principal

Discuss what a test suite's choice of counts says about the design: contractual counts belong at true boundaries (payments, outbound effects), incidental counts should not be asserted at all.

## The mode is a pluggable count strategy `verify(mock, mode)` hands every recorded invocation matching your description to a `VerificationMode`, which decides pass or fail. Mockito ships several count strategies on the `Mockito`/`org.mockito.Mockito` static API. ## never() `verify(mock, never()).sendEmail(any())` asserts that no matching invocation happened. It is literally implemented as `times(0)`, but the dedicated name produces a dedicated failure type and message ("Never wanted here ... but invoked here") that points at the offending call site, which `times(0)` phrasing would obscure. The scope matters: `never()` is about *one described invocation on one mock*. `verify(mailer, never()).send(eq("[email protected]"), any())` says nothing about `send` with other arguments, and nothing about the other methods on `mailer`. Asserting that a collaborator was left entirely alone is a different, whole-mock assertion. ## atLeastOnce() and atLeast(n) Lower bounds. `verify(metrics, atLeastOnce()).increment("orders")` passes with one call or fifty. Use them where the code legitimately may call more than the minimum and the extra calls are harmless: idempotent metrics, logging, a poll loop whose iteration count depends on timing. The cost is sensitivity: a lower-bound verification cannot catch the bug where a refactor makes the collaborator get hit ten times instead of once. If duplicate calls would be a defect - a payment charge, an outbound email, an expensive query - the lower bound is the wrong tool and `times(n)` is right. ## atMost(n) An upper bound: at most *n* matching calls, and zero passes too. It is the natural way to express "do not do this more than necessary" without pinning the exact number, e.g. "the cache must not load the same key more than once". Because zero passes, `atMost` alone rarely proves the behaviour you want; a common pattern is pairing an exact `times(1)` for the first read with the caching assertion, or simply using `times(1)` for both. One mechanical restriction: `atMost()` and `never()` are not supported inside ordered (`InOrder`) verification, because "at most n, in this position of the sequence" has no well-defined meaning; Mockito raises a usage error if you try. ## Choosing between them The question to ask is: *is the number part of the specification, or an artefact of how it happens to be implemented today?* - Number is the specification: charging a card once, publishing one event per order, opening one transaction. Use `times(n)` - the test should fail if it becomes two. - Number is an artefact: how many times a stream is polled, how often a clock is read, how many log lines are emitted. Use a bound, or do not verify it at all. A suite of `atLeastOnce()` everywhere is a smell in the opposite direction from over-verification: it looks like it checks behaviour but tolerates almost anything, so it neither documents nor protects. ## Failure semantics Each mode produces a different diagnosis. Exact and lower-bound failures where nothing matched report a not-invoked failure; exact and upper-bound failures where too many matched report a too-many-invocations failure with the extra call's stack trace; `never()` violations report a never-wanted failure. Reading which of these you got tells you immediately whether the problem is "my code did not call it", "it called it with different arguments", or "it called it more often than I expected".

  • never() is described as identical to times(0). If they behave the same, why does Mockito keep both?
    Readability and diagnostics. never() states the intent in the test's own words, and Mockito reports its violation as a dedicated never-wanted failure whose message contrasts 'never wanted here' with the actual call site. A times(0) failure would be phrased as a count mismatch, which reads oddly for an assertion whose point is that nothing should have happened.
  • A colleague uses atLeastOnce() throughout the suite because exact counts 'keep breaking'. What is your response?
    Breaking counts are information: either the production code is doing redundant work, or the test was pinning an incidental number. Blanket lower bounds silence both cases, so duplicate charges or duplicate emails would pass. I would keep exact counts where a repeat call is a real defect, drop the verification entirely where the count is meaningless, and reserve bounds for genuinely unconstrained loops.

saying these in an interview costs you the question

  • Believing verify(mock, never()).foo() also proves no other method on the mock was called
  • Using atLeastOnce() by default so tests stop failing
  • Thinking atMost(3) fails when the method was never called
  • Trying to use never() or atMost() inside an InOrder verification
  • Treating times(0) as an error because 'never' is the only valid form

context