skip to content

How do you give a Mockito mock a default answer of your own rather than one of the built-in Answers constants, and what kinds of behaviour justify writing one?

level: seniorimportance: should knowfreq 32%

answer

  1. Answer<T> = one method, lambda-friendly
  2. mock(Type.class, lambda) or withSettings().defaultAnswer
  3. InvocationOnMock: method, arguments, mock, callRealMethod
  4. AdditionalAnswers: returnsFirstArg, delegatesTo, answersWithDelay
  5. @Mock(answer=) takes only Answers constants

basics

~20 s

Pass an Answer implementation where an Answers constant would go: mock(Type.class, invocation -> ...) or withSettings().defaultAnswer(myAnswer). Inside, InvocationOnMock gives you the method, arguments, the mock and callRealMethod(). Justified for argument-dependent returns, failing loudly on unstubbed calls, or delegating to a fake.

solid answer

~40 s

`Answers` constants are just `Answer` implementations, so anywhere one is accepted you can pass your own. `Answer<T>` has a single method, `T answer(InvocationOnMock invocation)`, which makes it a lambda: `mock(Repo.class, inv -> { throw new AssertionError("unstubbed: " + inv.getMethod()); })`. With `@Mock` you cannot use a lambda — the annotation takes an `Answers` constant — so build such mocks in code, or via `withSettings().defaultAnswer(answer)`. `InvocationOnMock` exposes `getMethod()`, `getArguments()`/`getArgument(i)`, `getMock()`, and `callRealMethod()`. Good reasons to write one: - **fail fast**: throw on any unstubbed call, so tests never silently rely on a null; - **argument-dependent defaults**: echo an id back, return the saved entity, generate values from the input; - **delegation**: forward to an in-memory fake while keeping verification on the mock (`AdditionalAnswers.delegatesTo(fake)`). Check `AdditionalAnswers` first — `returnsFirstArg()`, `answersWithDelay()`, `delegatesTo()` already cover most cases.

code

java · 11 lines
java
Answer<Object> failOnUnstubbed = invocation -> {
    Method m = invocation.getMethod();
    if (m.getDeclaringClass() == Object.class) {
        return Answers.RETURNS_DEFAULTS.get().answer(invocation);
    }
    throw new AssertionError("Unstubbed call: " + m.getName()
            + Arrays.toString(invocation.getArguments()));
};

OrderRepository repo = mock(OrderRepository.class,
        withSettings().defaultAnswer(failOnUnstubbed));

go deeper

for a junior

Know that Answer is a one-method interface and that mock(Type.class, lambda) sets it as the fallback.

for a middle

Show the InvocationOnMock API and one concrete use, such as returning the saved argument.

for a senior

Discuss fail-fast defaults, delegatesTo fakes, and the readability cost of behaviour hidden in a default answer.

for a principal

Decide policy: whether the codebase gets a shared default answer, and how that interacts with strict stubs and test readability across teams.

## The Answer interface ```java public interface Answer<T> { T answer(InvocationOnMock invocation) throws Throwable; } ``` One abstract method, so it is a functional interface. Everything in the `Answers` enum — `RETURNS_DEFAULTS`, `RETURNS_SMART_NULLS`, `RETURNS_SELF`, `RETURNS_MOCKS`, `CALLS_REAL_METHODS` — is an instance of it. There is no privileged category: your own lambda sits at exactly the same level. An `Answer` is used in two places, and it is worth keeping them apart: 1. **as a per-stubbing answer**: `when(mock.find(anyLong())).thenAnswer(inv -> ...)` — applies to matching calls only; 2. **as the mock's default answer**: applies to every call that matches no stubbing. That is the subject here. ## Wiring a custom default answer ```java Answer<Object> failFast = inv -> { throw new AssertionError("Unstubbed call: " + inv.getMethod().getName()); }; Repo repo = mock(Repo.class, failFast); // or, alongside other settings: Repo repo2 = mock(Repo.class, withSettings() .defaultAnswer(failFast) .name("repo") .strictness(Strictness.STRICT_STUBS)); ``` The `@Mock(answer = ...)` attribute only accepts the `Answers` enum, so annotation-declared mocks cannot carry a lambda. Options: create those mocks in `@BeforeEach`, or register a project-level default by putting a class named `MockitoConfiguration` implementing `IMockitoConfiguration` on the test classpath and overriding `getDefaultAnswer()`. The latter changes every mock in the build and should be a deliberate, documented team decision. ## What InvocationOnMock gives you - `getMethod()` — the reflective `Method`, so you can branch on name or return type; - `getArguments()` / `getArgument(int)` / `getArgument(int, Class)` — the actual call arguments, typed; - `getMock()` — the mock itself, which is how `RETURNS_SELF` is implemented; - `callRealMethod()` — how `CALLS_REAL_METHODS` is implemented; only meaningful on a partial mock or spy. A generic default answer must cope with *any* return type on the interface, so returning a fixed value is rarely correct — branch on `getMethod().getReturnType()` or delegate to `ReturnsEmptyValues` for anything you do not handle. ## Patterns worth knowing **Fail fast on unstubbed calls.** The strictest possible default: any call you did not anticipate fails the test at the call site, with the method name. This removes the whole class of "NPE inside production code because a stub was missing" failures. The cost is that harmless calls — `toString()`, `hashCode()`, a logger asking the collaborator for a name — also fail, so real implementations usually whitelist `Object` methods. **Echo/derive from arguments.** `AdditionalAnswers.returnsFirstArg()` is the packaged version (`when(repo.save(any())).thenAnswer(returnsFirstArg())`), and as a *default* answer it is handy for save-and-return repositories. `returnsSecondArg()`, `returnsLastArg()`, `returnsArgAt(n)` complete the set. **Delegate to a fake.** `AdditionalAnswers.delegatesTo(new InMemoryRepo())` forwards every unstubbed call to a hand-written fake while keeping the object a Mockito mock, so `verify(...)` still works and individual methods can still be stubbed over the top. This is the cleanest way to combine a fake's realistic behaviour with a mock's interaction assertions. **Latency and async.** `answersWithDelay(millis, answer)` for timeout tests; `AdditionalAnswers.answer(...)` variants give typed lambdas that receive the arguments directly instead of an `InvocationOnMock`. ## Cautions A custom default answer is invisible action-at-a-distance: a reader of the test sees `repo.find(1)` and cannot tell what it returns without finding the mock's construction. Keep the answer small, name it, and prefer explicit stubbing when only one or two calls need special behaviour. Also, do not put nondeterminism (random values, real clocks, real I/O) inside an answer — a test that fails intermittently because a default answer generated a different value each run is much harder to debug than a missing stub. Finally, remember that stubbings always win over the default answer, so a custom default is a floor, not an override.

  • Why can't you put a custom Answer lambda on a @Mock annotation?
    Annotation attributes must be compile-time constants, and @Mock's answer attribute is typed as the Answers enum, so only its constants are expressible. To use a lambda you construct the mock programmatically — Mockito.mock(Type.class, lambda) or withSettings().defaultAnswer(lambda) — typically in a @BeforeEach method. The alternative is a project-wide IMockitoConfiguration, which is far broader in scope.
  • What does AdditionalAnswers.delegatesTo give you that simply using the fake directly does not?
    The object stays a Mockito mock, so you can still verify interactions on it and still stub individual methods to override the fake for a specific case. The fake supplies realistic behaviour for everything else, which keeps the test short. It is the usual way to get fake-like fidelity without giving up interaction assertions.
  • How does a custom default answer interact with explicit stubbings on the same mock?
    Stubbings take precedence. Mockito matches the invocation against registered stubbings first, and only calls the default answer when none matches. So a custom default sets the behaviour floor for everything you did not explicitly configure; adding a when(...) for a method silently removes that method from the answer's reach.

saying these in an interview costs you the question

  • Thinking custom answers can only be attached per stubbing, not as a mock's default
  • Returning a fixed typed value from a default answer that must serve all return types
  • Putting randomness, sleeps or real I/O inside an answer
  • Believing a custom default answer overrides explicit stubbings
  • Reinventing returnsFirstArg or delegatesTo by hand

context