skip to content

Explain Mockito's rule that if one argument uses a matcher, all arguments must use matchers. Why does this rule exist, and how do you satisfy it for a literal argument?

level: middleimportance: must knowfreq 75%

answer

  1. all-or-nothing per call
  2. wrap literals in eq()
  3. matchers pushed to thread-local stack, aligned by count
  4. InvalidUseOfMatchersException
  5. failure can surface in the NEXT test

basics

~20 s

If you use a matcher like any() for one argument of a call, you must use matchers for every argument of that call. For a plain value, wrap it in eq(). Mixing a matcher with a raw literal throws InvalidUseOfMatchersException.

solid answer

~50 s

Mockito's all-or-nothing rule: within a single stubbed or verified call, either every argument is a raw value or every argument is a matcher — you can't mix. So `verify(mock).update(any(), "ACTIVE")` is illegal; you must write `verify(mock).update(any(), eq("ACTIVE"))`. The reason is mechanical: matchers don't carry their argument position. Each matcher call pushes a matcher object onto a thread-local stack, and Mockito later pops them to align with parameters. If you supply two matchers but three arguments, Mockito can't tell which positions the matchers belong to, so it fails fast — often with `InvalidUseOfMatchersException` reporting a mismatch between the matcher count and the argument count. The fix is to convert every literal into an explicit matcher, almost always `eq(value)` for exact values, or `isNull()`/`same()` as appropriate. A common gotcha: the failure may surface on the *next* unrelated test because leftover matchers sit on the stack.

go deeper

for a junior

Knows the rule 'if one argument is a matcher, all must be' and that you wrap literals with eq().

for a middle

Can apply the rule under pressure, recognizes InvalidUseOfMatchersException, and knows eq() is the literal bridge.

for a senior

Explains the thread-local-stack/count mechanism that forces the rule and diagnoses delayed/cross-test failures from dangling matchers.

for a principal

Guides the team toward strict Mockito to surface misuse early, and can explain why the static-method matcher design makes the rule unavoidable rather than a mere implementation quirk.

## The rule, stated precisely For any **single** call inside `when(...)` or `verify(...)`, Mockito requires that **all arguments are matchers or none are**. You may not write some arguments as matchers and others as plain literals. ```java // ILLEGAL — one matcher, one literal verify(service).update(any(User.class), "ACTIVE"); // LEGAL — wrap the literal in eq() verify(service).update(any(User.class), eq("ACTIVE")); // ALSO LEGAL — no matchers at all verify(service).update(theUser, "ACTIVE"); ``` ## Why the rule exists — the mechanism To understand the rule you must understand that **a matcher is not a value**. When you call `any(User.class)`, it does two things: 1. Returns a **dummy** value of the right type (e.g. `null` for objects, `0` for `int`) so the surrounding method call compiles. 2. As a **side effect**, pushes a matcher object onto an **internal thread-local stack** maintained by Mockito. The method call `service.update(<dummy>, <dummy-or-literal>)` then executes against the mock. Mockito intercepts it and needs to decide, for each of the two parameters, *which matcher applies*. It does this by counting: it pops the matchers off the stack and lines them up with the argument positions, **right-to-left**, assuming there is exactly **one matcher per argument**. Now suppose you mixed: `update(any(User.class), "ACTIVE")`. Only **one** matcher was pushed (from `any`), but the method has **two** arguments. Mockito sees one matcher and two arguments and cannot unambiguously decide whether that single matcher belongs to argument 1 or argument 2 — the literal pushed nothing. Rather than guess, it raises `InvalidUseOfMatchersException` ("2 matchers expected, 1 recorded" style message). The rule exists purely because positions are inferred from **count**, not captured from the source. ## How to satisfy it Convert every plain argument into a matcher. The matcher that means "this exact value" is **`eq(value)`** — it matches with `.equals()`, exactly like the literal would have. Other position-fillers: - `eq(x)` — exact value (the usual fix). - `same(x)` — reference identity instead of equals. - `isNull()` — for a literal `null`. - `anyInt()` / `anyString()` / `any()` — if you actually don't care. ```java when(repo.find(eq(42L), any(Sort.class), eq(true))).thenReturn(page); ``` ## The delayed-failure gotcha Because matchers live on a thread-local stack, a malformed call can leave **dangling matchers** on the stack. The exception may then be thrown not where you made the mistake but at the **start of the next mock interaction** — sometimes in a *different test method*. Mockito's `MockitoJUnitRunner`/`MockitoExtension` in *strict* mode helps surface these earlier. If you see a confusing `InvalidUseOfMatchersException` or `UnfinishedStubbingException` in a test that looks fine, suspect a mixing mistake in the previous test. ## Why not just allow mixing? Mockito *could* in principle capture positions via bytecode, but the matcher API is plain static methods evaluated as ordinary Java expressions; there is no hook to know which parameter slot a `"ACTIVE"` literal will land in versus a matcher. The count-based stack is simple and fast, and the all-or-nothing rule is the price. `eq()` exists precisely to bridge literals into that world. ## Bottom line The rule is a direct consequence of matchers being side-effecting stack pushes with no positional identity. Remember: **one matcher anywhere → matchers everywhere; wrap literals in `eq()`.**

  • You have verify(mock).send(eq("hi"), recipient) and it throws InvalidUseOfMatchersException. What's wrong and how do you fix it?
    The first argument uses eq() (a matcher) but recipient is a raw literal, violating the all-or-nothing rule. Wrap the second too: verify(mock).send(eq("hi"), eq(recipient)).
  • Why might the exception appear in a test that doesn't use matchers at all?
    A mixing mistake in an earlier test can leave dangling matchers on the thread-local stack; the next mock interaction (possibly in another test) pops them and fails. Strict Mockito (MockitoExtension) surfaces it sooner.

saying these in an interview costs you the question

  • Saying you can mix one matcher with raw literals as long as types line up — you cannot.
  • Forgetting eq() and assuming Mockito auto-wraps literals when matchers are present.
  • Blaming the wrong test when a dangling matcher causes a delayed exception.
  • Confusing eq() (equals) with same() (reference identity).

context