How do you make a mock throw on the first call but succeed on retries, and when would you reach for thenAnswer/doAnswer instead of thenThrow?
answer
- chain: thenThrow(...).thenReturn(...) → per-call
- last stub is sticky
- doThrow(...).doNothing().when(mock).voidM() for void
- thenAnswer sees InvocationOnMock + getArgument(i)
- keep Answers thin → else use a fake
basics
~10 sChain stubs: when(mock.call()).thenThrow(new TimeoutException()).thenReturn(value). The first call throws, later calls return. Use thenAnswer/doAnswer when whether (or what) to throw depends on the actual arguments.
solid answer
~40 sMockito applies chained stubs to consecutive calls: when(mock.call()).thenThrow(new TimeoutException()).thenReturn(user) throws on the first invocation and returns user on every call after — perfect for testing retry logic. The last stub is sticky once reached. For void methods the do-chain is doThrow(ex).doNothing().when(mock).flush(). When the decision to throw depends on the arguments or call count, thenThrow isn't expressive enough; use thenAnswer (or doAnswer for void/spies). The Answer receives an InvocationOnMock, lets you read arguments via invocation.getArgument(i), and you can conditionally throw or compute a return. Keep Answers small — heavy logic in an Answer is a smell suggesting a hand-written fake or a real object would read better.
code
java · 12 lines// Fail twice then succeed — testing retry logic
when(client.fetch())
.thenThrow(new TimeoutException())
.thenThrow(new TimeoutException())
.thenReturn(payload);
// Argument-dependent throwing
when(repo.find(anyLong())).thenAnswer(inv -> {
long id = inv.getArgument(0);
if (id < 0) throw new IllegalArgumentException("id < 0");
return new User(id);
});go deeper
Knows you can chain thenThrow().thenReturn() so the first call fails and later calls succeed.
Explains chaining and last-stub stickiness, and the do-chain for void methods.
Reaches for thenAnswer/doAnswer for argument-dependent throwing, reads InvocationOnMock, and knows the do-form for spies.
Judges when an Answer is too heavy and a hand-written fake or real object yields clearer, more maintainable tests; sets retry-testing patterns.
## Consecutive-call stubbing Mockito lets a single stub define a **sequence** of behaviours, one per successive call, by chaining: ```java when(client.fetch()) .thenThrow(new TimeoutException()) // call #1 .thenThrow(new TimeoutException()) // call #2 .thenReturn(payload); // call #3 and onward ``` Rules: - Each chained item maps to the next invocation in order. - Once the **last** item is reached it becomes **sticky** — every further call repeats it. - You can freely mix `thenThrow` and `thenReturn` in one chain. A shorthand: `thenThrow(A.class, B.class)` (or `thenThrow(a, b)`) passes several exceptions at once, equivalent to chaining them. This is the canonical way to test **retry** logic: "fail twice, then succeed — assert the code retried and eventually returned the value." For **void** methods use the do-chain: ```java doThrow(new IllegalStateException()).doNothing().when(buffer).flush(); ``` ## When thenThrow isn't enough: thenAnswer / doAnswer `thenThrow` and `thenReturn` are **static** — they don't see the call's arguments. When the behaviour must depend on *what was passed* (or other dynamic state), use an **`Answer`**: ```java when(repo.find(anyLong())).thenAnswer(invocation -> { long id = invocation.getArgument(0); if (id < 0) throw new IllegalArgumentException("id < 0"); return new User(id); }); ``` An `Answer<T>` is a callback that receives an **`InvocationOnMock`**, exposing: - `getArgument(int)` — a typed argument by position, - `getArguments()` — all args, - `getMock()` — the mock itself, - `callRealMethod()` — invoke the real implementation (useful on spies). From inside the lambda you can **conditionally throw** an exception, compute a return based on inputs, or track call counts. `doAnswer(...).when(mock).method()` is the void-/spy-safe form. ## Choosing between them | Need | Use | |---|---| | Always throw the same exception | `thenThrow` / `doThrow` | | Different behaviour per successive call | chained `thenThrow().thenReturn()...` | | Behaviour depends on arguments / dynamic state | `thenAnswer` / `doAnswer` | | Void method, any of the above | the `do*` family | ## Caution: keep Answers thin An `Answer` is real code running inside your test. Large, branchy Answers are hard to read and often re-implement the very logic you're trying to fake. If an Answer grows, prefer a small **hand-written fake/stub class** or a real object — the test will be clearer. Reserve Answers for genuinely argument-dependent behaviour. ## Summary - Chain stubs for per-call behaviour; the last one sticks. - `thenAnswer`/`doAnswer` give access to the invocation so you can throw or return based on arguments. - Use the `do*` forms for void methods and spies; keep Answers small.
- What happens on the 4th call if you chained three behaviours?The third (last) behaviour repeats — the final stub in a chain is sticky for all subsequent calls.
- How does an Answer read the method arguments?Through the InvocationOnMock passed to it, e.g. invocation.getArgument(0) or invocation.getArguments().
saying these in an interview costs you the question
- Thinking each call re-runs the whole chain (it advances and then sticks on the last)
- Using thenThrow when behaviour must depend on arguments (needs thenAnswer)
- Putting heavy logic inside an Answer instead of a hand-written fake