skip to content

What does the only() verification mode assert in Mockito, and how does it differ from a plain single-call verification?

level: middleimportance: nice to knowfreq 30%

answer

  1. only() = exactly one call AND nothing else on that mock
  2. scoped to one mock, not the whole test
  3. no only(times(2)) - not composable
  4. great for one-call ports, bad for rich collaborators
  5. failure is unwanted-interaction shaped

basics

~20 s

verify(mock, only()).foo() asserts two things at once: foo() was called exactly once, and it was the only invocation on that mock. A plain verify(mock).foo() checks only the first half - other methods on the mock may also have been called.

solid answer

~40 s

`only()` is a `VerificationMode` that combines an exact single-call check on the described invocation with a whole-mock exclusivity check: nothing else was called on that mock at all. `verify(cache, only()).get("k")` fails if the code also called `cache.put(...)`, whereas `verify(cache).get("k")` would pass. It is a convenience shorthand for a single-collaborator mock whose entire expected protocol is one call - useful for a narrow port such as a clock or an id generator. Beyond that it over-specifies: every future call added to the collaborator, however incidental, breaks the test. Practical notes: it applies to one mock at a time, so you cannot express "only this across several mocks"; the failure it produces is the no-interactions-wanted family, listing the unexpected call; and because it is exclusivity plus a count, it is not usable in ordered verification.

code

java · 13 lines
java
@Test
void readsTheClockExactlyOnceAndNothingElse() {
    service.stamp(document);

    verify(clock, only()).instant();   // fails if clock.getZone() was also called
}

@Test
void plainVerifyIgnoresOtherCalls() {
    service.stamp(document);

    verify(clock).instant();           // passes even if clock.getZone() was called
}

go deeper

for a junior

Recall that only() means the described call happened once and it was the mock's only interaction.

for a middle

Contrast it explicitly with times(1), name the whole-mock scope, and give one collaborator where exclusivity is genuinely part of the contract.

for a senior

Frame it as over-specification risk: it pins a collaborator's entire protocol, so it belongs on narrow ports and nowhere else.

for a principal

Use it to talk about test coupling budgets - which collaborator protocols are stable enough to freeze, and why most are not.

## The two assertions bundled into one Every ordinary Mockito verification is scoped to a *described invocation*: `verify(mock, times(1)).foo(x)` says nothing about `mock.bar()`, nor about `foo` called with a different argument. `only()` widens the scope. `verify(mock, only()).foo(x)` asserts: 1. `foo(x)` was invoked exactly once, and 2. the total number of invocations recorded on `mock` is one - so that call was the *only* thing that happened to it. That second clause is what people miss. It turns a targeted assertion into a statement about the mock's whole interaction history. ## When it is genuinely useful The fit is a **narrow collaborator with a one-call protocol**. Examples: an `IdGenerator` that should be asked for an id once; a `Clock` port the code should read once per operation rather than re-reading and risking inconsistent timestamps; a `Publisher` that must emit exactly one event and do nothing else. In those cases exclusivity is genuinely part of the specification, and `only()` says it in one line rather than a call verification plus a separate exhaustive check. ## When it hurts For a rich collaborator - a repository, an HTTP client wrapper, a session - `only()` freezes the entire protocol. Adding an innocuous `repo.count()` or a new `close()` call to production code fails a test that was nominally about `save`. That is over-specification: the test now fails for changes that break nothing. In those cases verify the call you care about and let the rest be unconstrained. ## Relationship to other modes `only()` is not composable with a count - there is no `only(times(2))`. If you need "exactly two calls to this method and nothing else on the mock", express it as an exact-count verification followed by an exhaustive check on that mock. Because the assertion includes "nothing else at all", it also interacts badly with stubbed calls that the code legitimately makes: any stubbed method the code invokes counts as an interaction and will trip the exclusivity clause. It is likewise not meaningful inside ordered verification, where each step consumes invocations in sequence rather than asserting over the mock's whole history. ## Reading its failure A violation surfaces as an unwanted-interaction failure naming the extra invocation and its stack trace, alongside the wanted one. That message is often the moment a candidate realises `only()` did more than they intended - if the extra call listed is something harmless, the mode was the wrong choice, not the production code. ## Practical guidance Treat `only()` as a readability shortcut for tiny ports, not a default. If you find yourself reaching for it on a mock with more than two or three methods, the test is describing implementation shape rather than behaviour, and a targeted verification will age far better.

  • Your test uses verify(repo, only()).save(order) and starts failing after someone adds a repo.existsById(id) guard to the production method. Is that a real regression?
    No - the behaviour under test, saving the order once, is unchanged; the test failed on the exclusivity clause that only() smuggles in. The right fix is to drop only() in favour of verify(repo).save(order), and to verify the existence check separately if it is actually part of the specification. Keeping only() here would make every future call on the repository a test failure.
  • How would you express 'exactly two calls to send and nothing else on this mock'?
    only() cannot carry a count, so it must be two assertions: verify(mock, times(2)).send(payload) for the count, then an exhaustive no-further-interactions check on that same mock to close off everything else. That pairing states both halves explicitly and produces clearer failures than a single bundled mode would.

saying these in an interview costs you the question

  • Thinking only() just means 'exactly once' like times(1)
  • Believing only() covers all mocks in the test rather than the one passed to verify
  • Trying to write only(times(2))
  • Using only() on a repository or client with many methods and calling the resulting failures regressions
  • Assuming stubbed calls are exempt from only()'s exclusivity check

context