skip to content

Matchers & Captors

Flexible argument matching for stubs and verification, the strict all-or-none rule that trips everyone at least once, and ArgumentCaptor for asserting on what was actually passed. A favorite interview area because InvalidUseOfMatchersException errors reveal who understands the matcher stack.

on this pageshow

explore

questions

16

When writing Mockito stubs and verifications, when should you wrap a plain value in ArgumentMatchers.eq(), and when is passing the raw value directly the better style?

level: juniorimportance: must knowfreq 60%

answer

  1. eq() = Equals matcher + stack entry
  2. Only needed when the call already has a matcher
  3. Raw args are compared with equals() anyway
  4. No equals() override means identity comparison
  5. capture() is a matcher too - wrap siblings

basics

~20 s

Use eq() only when the same call already uses another matcher, because matchers and raw values cannot be mixed. If no argument needs a wildcard, pass plain values - eq() everywhere is noise with identical behaviour.

solid answer

~40 s

`eq(x)` matches arguments equal to `x` - exactly what a raw value does - but it also registers an entry on Mockito's matcher stack. Since one invocation must use zero matchers or a matcher per argument, `eq()` exists to promote literals in a call that already needs `any()`, `argThat()`, or a captor. So the rule of thumb: - No matcher needed anywhere in the call: `verify(repo).save(user)` - plainest and most readable. - At least one matcher: promote everything, `verify(repo).find(eq(42), any(Filter.class))`. Two caveats worth naming. `eq()` uses `equals()`, so for a class without a meaningful `equals()` it degrades to identity comparison - use `same()` for identity on purpose or an `ArgumentCaptor`/`argThat` for field-level assertions. And `eq(null)` is legal but `isNull()` reads better.

code

java · 8 lines
java
// nothing needs a wildcard -> raw values
verify(repo).save(user);

// one wildcard -> promote the rest
verify(repo).find(eq(42), any(Filter.class));

// capture() is a matcher, so id must be eq()
verify(repo).update(eq(42L), captor.capture());

go deeper

for a junior

State the rule: eq() is how you keep a literal legal in a call that already uses a matcher, and plain values are fine otherwise.

for a middle

Add that eq() delegates to equals(), so value types without equals() silently degrade to identity comparison, and mention same() and isNull() as intent-revealing alternatives.

for a senior

Discuss failure-message quality and mutable arguments: prefer captors or argThat for object-shaped assertions so a mismatch reports the offending field rather than a toString diff.

for a principal

Position it as a team convention: agree when equality-based verification is acceptable versus capture-and-assert, and require equals/hashCode on verification-relevant value types so tests do not encode accidental identity semantics.

## What eq() is `ArgumentMatchers.eq(value)` returns a dummy (`null`, `0`, `false`) after pushing an `Equals` matcher onto Mockito's thread-local matcher stack. That matcher later evaluates `value.equals(actualArgument)` - the identical comparison Mockito applies when you pass the value raw. So `eq()` never changes *what* matches; it changes only the bookkeeping. ## Why it exists at all Because of the all-or-none rule: within a single mock invocation Mockito accepts zero matchers (raw arguments compared with equals) or exactly one matcher per argument. There is no middle ground, since matchers return dummies indistinguishable from real values. So the moment one argument needs a wildcard, every other argument must become a matcher too - and `eq()` is the wrapper that makes a literal into one. ```java verify(repo).find(eq(42), any(Filter.class)); // required verify(repo).save(user); // eq() would be pure noise ``` ## When raw is better If the call needs no wildcard, pass raw values. It is shorter, needs no static import, and is what most codebases do. Reviewers reading `verify(mailer).send(eq("[email protected]"), eq(subject))` reasonably ask what the matcher is for; the answer is nothing, which is a small readability tax on every reader. ## When eq() is required 1. **Mixed calls** - anything alongside `any()`, `anyString()`, `argThat(...)`, `isNull()`, or `captor.capture()`. 2. **Captor calls** - `verify(repo).update(eq(id), captor.capture())`: `capture()` is itself a matcher, so the id must be wrapped. 3. **Generic-heavy code** where an explicit `eq(...)` with a type witness (`ArgumentMatchers.<List<String>>eq(list)`) helps inference. ## Sharp edges **equals() semantics.** `eq()` delegates to the argument's `equals()`. A DTO without `equals()` falls back to `Object.equals`, i.e. reference identity, so a stub that looks value-based silently becomes identity-based and never matches an object rebuilt inside the code under test. Options: implement `equals()`, use `argThat(...)` on the fields you care about, or capture and assert with AssertJ - the last usually gives the best failure message. **Arrays.** `eq(new int[]{1,2})` compares with `Arrays.equals` via Mockito's internal `Equality` helper, which is friendlier than raw `equals()` on arrays - but do not assume that for arbitrary array-holding value objects. **Mutable arguments.** If the production code mutates the object after the call, `eq()` compares the mutated state at verification time, because the mock stores a reference. That is a classic source of "verification passes/fails inexplicably"; capture-and-assert or a defensive copy is the remedy. **Nulls.** `eq(null)` compiles and works, but `isNull()` states intent and avoids ambiguity in overload resolution. **Identity vs equality.** `same(x)` matches only if the argument is the same reference. Use it deliberately when identity is the contract (for example a cached singleton), not as a workaround for a missing `equals()`. ## Interview framing A junior answer states the mixing rule and the fix. A stronger answer adds the style guidance (do not wrap when nothing else is a matcher) and the `equals()` trap - that `eq()` is only as good as the argument type's equality contract, which is exactly why captors and `argThat` exist for value-shaped assertions.

  • A stub written with eq(dto) never matches, although the production code clearly passes an equal-looking DTO. What is the likely cause?
    The DTO almost certainly does not override equals(), so eq() falls back to Object.equals - reference identity - and the instance built inside the code under test is a different object. Fix by implementing equals/hashCode on the value type, or by switching to argThat/ArgumentCaptor and asserting the fields that matter, which also produces a far clearer failure message.
  • How do eq() and same() differ?
    eq(x) matches when x.equals(actual), so any equal instance passes; same(x) matches only when the argument is the identical reference. Use same() when identity is genuinely part of the contract, such as verifying that a cached or injected instance was forwarded untouched, not as a patch for a missing equals() implementation.

saying these in an interview costs you the question

  • Wrapping every argument in eq() by default and calling it best practice
  • Believing eq() compares fields reflectively rather than delegating to equals()
  • Thinking eq() is required whenever any matcher appears anywhere in the test rather than in that one call
  • Using eq() on a mutable object and not realising the comparison happens later against possibly mutated state
  • Saying eq(null) is illegal - it works, though isNull() is clearer

context

open as a page

Explain what Mockito's ArgumentCaptor is for, how you create one and wire it into a verification, and how you read the captured value afterwards.

level: juniorimportance: must knowfreq 70%

basics

~10 s

An ArgumentCaptor grabs the actual argument a mock received so you can assert on it. Create it with ArgumentCaptor.forClass(X.class) or @Captor, pass captor.capture() inside verify(...), then read captor.getValue() and assert normally.

open as a page

In Mockito, what is an argument matcher such as any(), anyString() or anyInt(), and why would you stub or verify a call with one instead of passing a concrete expected value?

level: juniorimportance: must knowfreq 70%

basics

~20 s

A matcher is a placeholder used inside Mockito's when() or verify() saying 'any argument fitting this description' instead of one exact value. any() matches anything, anyString() any non-null String, anyInt() any int. Use them when the value is irrelevant or unpredictable.

open as a page

Mockito throws InvalidUseOfMatchersException when a stubbed call mixes an argument matcher such as ArgumentMatchers.anyInt() with a plain literal argument. Explain the rule this violates and how Mockito's argument matchers are implemented under the hood.

level: middleimportance: must knowfreq 72%

basics

~20 s

Matchers do not return values you pass in. Each one pushes a matcher object onto a thread-local stack and returns a dummy (0, false, null). Mockito only sees dummies, so per call all arguments must be matchers or none. Wrap literals in eq().

open as a page

Mockito's built-in matchers cannot express a condition like 'an Order whose total exceeds 100 and whose status is PENDING'. How do you match an argument on an arbitrary condition when stubbing or verifying with Mockito?

level: middleimportance: must knowfreq 45%

basics

~20 s

Use argThat(ArgumentMatcher) with a predicate: verify(repo).save(argThat(o -> o.total() > 100 && o.status() == PENDING)). ArgumentMatcher is a functional interface with one boolean matches(T) method, so a lambda works. It composes with the built-in matchers in the same call.

open as a page

A mocked collaborator is called several times during one test and you need to assert on each argument it received. Explain how Mockito's ArgumentCaptor behaves across multiple invocations and how you would write that verification.

level: middleimportance: should knowfreq 52%

basics

~10 s

Verify with a count - verify(mock, times(3)).send(captor.capture()) - then read captor.getAllValues(), a list in invocation order. getValue() alone returns only the last one, so asserting on it silently ignores earlier calls.

open as a page

Mockito's ArgumentMatchers class offers any(), any(SomeClass.class) and isA(SomeClass.class). How do these three differ in what they will actually match?

level: middleimportance: should knowfreq 50%

basics

~20 s

any() matches absolutely anything, including null, with no type check. any(SomeClass.class) is an alias of isA(SomeClass.class) in Mockito 2 and later: both require a non-null instance of that type (subclasses included). The class argument in any(...) is not just a cast hint.

open as a page

Using Mockito, will verify(repo).save(anyString()) match a call where the production code passed null? How do you write a matcher that accepts null, or that accepts either null or a String?

level: middleimportance: should knowfreq 45%

basics

~10 s

No. Since Mockito 2.1.0 anyString() and the other typed matchers reject null. Use isNull() to require null, nullable(String.class) to accept null or a String, or any() which matches everything including null.

open as a page

A Mockito verification written as verify(service).setRetryCount(argThat(n -> n > 3)) blows up with a NullPointerException before any assertion is reported, on a method whose parameter is a primitive int. What is happening, and which Mockito API fixes it?

level: middleimportance: should knowfreq 30%

basics

~20 s

argThat is generic and returns null. Java must unbox that null into the primitive int parameter, which throws NullPointerException before Mockito compares anything. Use intThat(n -> n > 3) - and the siblings longThat, doubleThat, booleanThat and so on - which return a primitive default.

open as a page

A Mockito test suite fails with InvalidUseOfMatchersException pointing at a test method whose code looks correct, and the failure disappears when that test runs alone. Explain how this happens and how you would locate the real culprit.

level: seniorimportance: should knowfreq 42%

basics

~20 s

An earlier test registered matchers that were never consumed by a mock call, leaving Mockito's thread-local matcher stack dirty. The next mock interaction - in another test - sees leftover matchers and reports the misuse there. Run with MockitoExtension or call validateMockitoUsage() in teardown to attribute it correctly.

open as a page

In Mockito you can constrain a mock's argument either with a custom predicate matcher passed to verify, or by capturing the argument and asserting on it afterwards. How do you choose between the two, and where does each belong?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Use a predicate matcher when the constraint selects which call you mean - especially during stubbing, where capturing is not available. Capture and assert when you want to inspect a rich payload, because assertion libraries report which field differed while a failed predicate only says no matching invocation was found.

open as a page

A Mockito verification written as verify(repo).save(any()) still passes after a bug is introduced that saves the wrong object. Using Mockito's built-in matchers, how would you tighten it, and what do eq() and same() each buy you?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Replace any() with a matcher that constrains the value: eq(expected) compares with equals(), same(expected) requires the identical instance, refEq(expected) compares fields reflectively when the class has no equals(). Keep any() only for arguments the test genuinely does not assert.

open as a page

A Mockito verification using a lambda-based custom argument matcher fails, and the report prints something like Test$$Lambda$14/0x0000000800c0a440@6d06d69c instead of anything readable. How do you make custom argument matchers produce diagnosable failure messages?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Mockito prints the matcher's toString() in the 'Argument(s) are different' report, and a lambda's toString() is the synthetic class name. Implement ArgumentMatcher as a named class overriding toString() with a human description, or drop the matcher and assert on the extracted value instead.

open as a page

In a large test suite using Mockito, argument assertions can live inside the verification as custom predicate matchers, or be pulled out and asserted separately on the recorded value. How do you decide which, and what does each choice cost in diagnosability and coupling?

level: principalimportance: should knowfreq 25%

basics

~20 s

Use a predicate matcher when the condition must select which invocation or which stubbed behaviour applies. Pull the assertion out when you need a readable explanation of what was wrong. Matchers discriminate, assertions explain - and matchers also work in stubbing, where extracted assertions cannot.

open as a page

A teammate wants to reduce duplication in Mockito tests by storing an argument matcher in a field or returning one from a helper method and reusing it across several verifications. Explain what goes wrong and what a safe refactoring looks like.

level: middleimportance: nice to knowfreq 30%

basics

~20 s

A matcher is not a reusable value - the call registers it on a thread-local stack and returns a dummy. Storing it in a field registers once at initialisation and yields a dummy afterwards, breaking matcher counts. Extract a helper that returns the matcher expression, and call it inline at each use site.

open as a page

You need a Mockito ArgumentCaptor for an argument of type List<String>. Explain the problem with ArgumentCaptor.forClass and what the alternatives are.

level: middleimportance: nice to knowfreq 33%

basics

~20 s

forClass takes a Class object, and List<String>.class does not exist - you can only pass List.class, which yields a raw-typed captor and an unchecked assignment warning. Use the @Captor annotation, whose field generics are read from the declaration, or ArgumentCaptor.captor() in newer Mockito versions.

open as a page