0
# Additional Answer Behaviors
1
2
This section covers advanced stubbing behaviors that go beyond basic return values and exception throwing, providing sophisticated answer strategies for complex testing scenarios.
3
4
## Argument-Based Return Values
5
6
### Return First Argument
7
8
Return the first parameter of an invocation as the method's return value.
9
10
```java { .api }
11
public static <T> Answer<T> returnsFirstArg()
12
```
13
14
**Usage Examples:**
15
16
```java
17
CarKeyFob mockKeyFob = mock(CarKeyFob.class);
18
PersonService mockPerson = mock(PersonService.class);
19
20
// Return the first argument passed to the method
21
when(mockKeyFob.authenticate(any(CarKey.class))).will(returnsFirstArg());
22
when(mockPerson.remember(any(Dream.class), any(Dream[].class))).will(returnsFirstArg());
23
24
// Use the mock
25
CarKey key = new CarKey("ABC123");
26
CarKey result = mockKeyFob.authenticate(key); // Returns the same CarKey instance
27
28
Dream dream1 = new Dream("flying");
29
Dream result2 = mockPerson.remember(dream1, new Dream("falling")); // Returns dream1
30
31
// Works with varargs - returns first individual argument
32
Dream[] dreams = {new Dream("running"), new Dream("swimming")};
33
Dream result3 = mockPerson.remember(dreams[0], dreams[1]); // Returns dreams[0]
34
```
35
36
### Return Second Argument
37
38
Return the second parameter of an invocation as the method's return value.
39
40
```java { .api }
41
public static <T> Answer<T> returnsSecondArg()
42
```
43
44
**Usage Examples:**
45
46
```java
47
TraderService mockTrader = mock(TraderService.class);
48
PersonService mockPerson = mock(PersonService.class);
49
50
// Return the second argument passed to the method
51
when(mockTrader.apply(any(Formula.class), any(Swap.class))).will(returnsSecondArg());
52
when(mockPerson.remember(any(Dream.class), any(Dream[].class))).will(returnsSecondArg());
53
54
// Use the mock
55
Formula formula = new Formula("Lee's Formula");
56
Swap swap = new CreditDefaultSwap();
57
Swap result = mockTrader.apply(formula, swap); // Returns the swap instance
58
59
Dream dream1 = new Dream("flying");
60
Dream dream2 = new Dream("falling");
61
Dream[] otherDreams = mockPerson.remember(dream1, dream2, new Dream("running"));
62
// Returns otherDreams array when second parameter is varargs
63
```
64
65
### Return Last Argument
66
67
Return the last parameter of an invocation as the method's return value.
68
69
```java { .api }
70
public static <T> Answer<T> returnsLastArg()
71
```
72
73
**Usage Examples:**
74
75
```java
76
PersonService mockPerson = mock(PersonService.class);
77
78
// Return the last argument passed to the method
79
when(mockPerson.remember(any(Dream.class), any(), any(), any())).will(returnsLastArg());
80
81
// Use the mock
82
Dream dream1 = new Dream("flying");
83
Dream dream2 = new Dream("falling");
84
Dream dream3 = new Dream("running");
85
Dream dream4 = new Dream("swimming");
86
87
Dream result = mockPerson.remember(dream1, dream2, dream3, dream4); // Returns dream4
88
89
// Works with varargs - returns last element or varargs array
90
Dream[] varargDreams = {new Dream("dancing")};
91
Dream[] result2 = mockPerson.rememberArray(dream1, dream2, dream3, varargDreams);
92
// Returns varargDreams array if return type matches varargs type
93
```
94
95
### Return Argument at Position
96
97
Return the parameter at a specific position in the invocation.
98
99
```java { .api }
100
public static <T> Answer<T> returnsArgAt(int position)
101
```
102
103
**Usage Examples:**
104
105
```java
106
PersonService mockPerson = mock(PersonService.class);
107
108
// Return argument at index 2 (zero-based)
109
when(mockPerson.remember(any(), any(), any(), any())).will(returnsArgAt(2));
110
111
// Use the mock
112
Dream dream1 = new Dream("flying");
113
Dream dream2 = new Dream("falling");
114
Dream dream3 = new Dream("running");
115
Dream dream4 = new Dream("swimming");
116
117
Dream result = mockPerson.remember(dream1, dream2, dream3, dream4); // Returns dream3
118
119
// Works with varargs expansion
120
when(mockPerson.remember(any(Dream.class), any(Dream[].class))).will(returnsArgAt(2));
121
Dream expandedResult = mockPerson.remember(dream1, dream2, dream3, dream4);
122
// Returns dream3 (varargs expanded to individual arguments)
123
```
124
125
## Call Delegation
126
127
### Delegate to Real Object
128
129
Forward all method calls to a delegate object, useful for partial mocks and final classes.
130
131
```java { .api }
132
public static <T> Answer<T> delegatesTo(Object delegate)
133
```
134
135
**Usage Examples:**
136
137
```java
138
// Final class that can't be spied normally
139
final class DontYouDareToMockMe implements List<String> {
140
private List<String> list = new ArrayList<>();
141
142
@Override
143
public boolean add(String item) {
144
return list.add(item);
145
}
146
147
@Override
148
public String get(int index) {
149
return list.get(index);
150
}
151
// ... other List methods
152
}
153
154
DontYouDareToMockMe awesomeList = new DontYouDareToMockMe();
155
awesomeList.add("delegated-item");
156
157
// Create mock that delegates to the real object
158
List<String> mockList = mock(List.class, delegatesTo(awesomeList));
159
160
// Method calls are forwarded to awesomeList
161
String result = mockList.get(0); // Returns "delegated-item"
162
163
// Important: Use doReturn for stubbing to avoid calling real method
164
doReturn("stubbed-value").when(mockList).get(0);
165
166
// Delegate can be different type with compatible method signatures
167
UserRepository realRepo = new DatabaseUserRepository();
168
UserRepository mockRepo = mock(UserRepository.class, delegatesTo(realRepo));
169
// Calls will be forwarded to realRepo
170
```
171
172
## Collection-Based Returns
173
174
### Return Elements from Collection
175
176
Return elements from a collection sequentially, repeating the last element forever.
177
178
```java { .api }
179
public static <T> Answer<T> returnsElementsOf(Collection<?> elements)
180
```
181
182
**Usage Examples:**
183
184
```java
185
NumberService mockService = mock(NumberService.class);
186
187
// Return elements in sequence
188
List<Integer> numbers = Arrays.asList(1, 2, 3);
189
when(mockService.getNextNumber()).thenAnswer(returnsElementsOf(numbers));
190
191
// Use the mock
192
int first = mockService.getNextNumber(); // Returns 1
193
int second = mockService.getNextNumber(); // Returns 2
194
int third = mockService.getNextNumber(); // Returns 3
195
int fourth = mockService.getNextNumber(); // Returns 3 (last element repeats)
196
int fifth = mockService.getNextNumber(); // Returns 3 (continues repeating)
197
198
// Equivalent to traditional stubbing
199
// when(mockService.getNextNumber()).thenReturn(1, 2, 3);
200
201
// Works with any collection type
202
Set<String> statuses = new LinkedHashSet<>(Arrays.asList("pending", "processing", "completed"));
203
when(mockService.getStatus()).thenAnswer(returnsElementsOf(statuses));
204
```
205
206
## Delayed Answers
207
208
### Answer with Delay
209
210
Return an answer after a specified delay in milliseconds.
211
212
```java { .api }
213
public static <T> Answer<T> answersWithDelay(long sleepyTime, Answer<T> answer)
214
```
215
216
**Usage Examples:**
217
218
```java
219
NetworkService mockService = mock(NetworkService.class);
220
221
// Simulate network latency
222
Answer<String> delayedResponse = answersWithDelay(1000, invocation -> "response");
223
when(mockService.fetchData()).thenAnswer(delayedResponse);
224
225
// Use with other answers
226
Answer<String> delayedArgReturn = answersWithDelay(500, returnsFirstArg());
227
when(mockService.echo(anyString())).thenAnswer(delayedArgReturn);
228
229
// Combine with exception throwing
230
Answer<String> delayedFailure = answersWithDelay(200,
231
invocation -> { throw new TimeoutException("Simulated timeout"); });
232
when(mockService.unreliableCall()).thenAnswer(delayedFailure);
233
234
// Use the mock
235
long start = System.currentTimeMillis();
236
String result = mockService.fetchData(); // Takes ~1000ms to return
237
long elapsed = System.currentTimeMillis() - start; // ~1000ms
238
```
239
240
## Functional Interface Answers
241
242
### Typed Return Answers (1-6 Parameters)
243
244
Create strongly-typed answers using functional interfaces for methods that return values.
245
246
```java { .api }
247
public static <T, A> Answer<T> answer(Answer1<T, A> answer)
248
public static <T, A, B> Answer<T> answer(Answer2<T, A, B> answer)
249
public static <T, A, B, C> Answer<T> answer(Answer3<T, A, B, C> answer)
250
public static <T, A, B, C, D> Answer<T> answer(Answer4<T, A, B, C, D> answer)
251
public static <T, A, B, C, D, E> Answer<T> answer(Answer5<T, A, B, C, D, E> answer)
252
public static <T, A, B, C, D, E, F> Answer<T> answer(Answer6<T, A, B, C, D, E, F> answer)
253
```
254
255
**Usage Examples:**
256
257
```java
258
UserService mockService = mock(UserService.class);
259
260
// Single parameter answer with type safety
261
Answer1<User, String> userByName = name -> new User(name.toLowerCase());
262
when(mockService.findUser(anyString())).thenAnswer(answer(userByName));
263
264
// Two parameter answer
265
Answer2<String, String, Integer> formatter = (name, age) -> name + " (" + age + ")";
266
when(mockService.formatUser(anyString(), anyInt())).thenAnswer(answer(formatter));
267
268
// Three parameter answer with complex logic
269
Answer3<Double, Double, Double, String> calculator = (x, y, operation) -> {
270
switch (operation) {
271
case "add": return x + y;
272
case "multiply": return x * y;
273
default: return 0.0;
274
}
275
};
276
when(mockService.calculate(anyDouble(), anyDouble(), anyString()))
277
.thenAnswer(answer(calculator));
278
279
// Using method references
280
Answer1<String, String> upperCaser = String::toUpperCase;
281
when(mockService.transform(anyString())).thenAnswer(answer(upperCaser));
282
283
// Lambda expressions for simple cases
284
when(mockService.processNumber(anyInt()))
285
.thenAnswer(answer((Integer n) -> n * 2));
286
```
287
288
### Typed Void Answers (1-6 Parameters)
289
290
Create strongly-typed answers using functional interfaces for void methods.
291
292
```java { .api }
293
public static <A> Answer<Void> answerVoid(VoidAnswer1<A> answer)
294
public static <A, B> Answer<Void> answerVoid(VoidAnswer2<A, B> answer)
295
public static <A, B, C> Answer<Void> answerVoid(VoidAnswer3<A, B, C> answer)
296
public static <A, B, C, D> Answer<Void> answerVoid(VoidAnswer4<A, B, C, D> answer)
297
public static <A, B, C, D, E> Answer<Void> answerVoid(VoidAnswer5<A, B, C, D, E> answer)
298
public static <A, B, C, D, E, F> Answer<Void> answerVoid(VoidAnswer6<A, B, C, D, E, F> answer)
299
```
300
301
**Usage Examples:**
302
303
```java
304
LoggingService mockService = mock(LoggingService.class);
305
306
// Single parameter void answer
307
VoidAnswer1<String> logger = message -> System.out.println("LOG: " + message);
308
doAnswer(answerVoid(logger)).when(mockService).log(anyString());
309
310
// Two parameter void answer
311
VoidAnswer2<String, LogLevel> levelLogger = (message, level) ->
312
System.out.println("[" + level + "] " + message);
313
doAnswer(answerVoid(levelLogger)).when(mockService).log(anyString(), any(LogLevel.class));
314
315
// Complex void behavior with side effects
316
List<String> auditLog = new ArrayList<>();
317
VoidAnswer3<String, String, Date> auditor = (user, action, timestamp) -> {
318
auditLog.add(user + " performed " + action + " at " + timestamp);
319
};
320
doAnswer(answerVoid(auditor)).when(mockService).audit(anyString(), anyString(), any(Date.class));
321
322
// Method reference for existing methods
323
VoidAnswer1<String> printer = System.out::println;
324
doAnswer(answerVoid(printer)).when(mockService).output(anyString());
325
326
// Lambda for state modification
327
AtomicInteger counter = new AtomicInteger(0);
328
doAnswer(answerVoid((String msg) -> counter.incrementAndGet()))
329
.when(mockService).log(anyString());
330
```
331
332
## Complex Answer Combinations
333
334
### Combining Multiple Answer Strategies
335
336
Create sophisticated mock behaviors by combining different answer types.
337
338
**Usage Examples:**
339
340
```java
341
PaymentService mockService = mock(PaymentService.class);
342
343
// Combine delegation with delay for realistic simulation
344
PaymentProcessor realProcessor = new DefaultPaymentProcessor();
345
Answer<PaymentResult> realisticAnswer = answersWithDelay(500, delegatesTo(realProcessor));
346
when(mockService.processPayment(any())).thenAnswer(realisticAnswer);
347
348
// Sequential behavior with different answer types
349
when(mockService.getTransactionId())
350
.thenAnswer(returnsElementsOf(Arrays.asList("TX001", "TX002", "TX003")))
351
.thenAnswer(answer((InvocationOnMock inv) -> "TX" + System.currentTimeMillis()));
352
353
// Argument-dependent answers with functional interfaces
354
Answer2<String, String, Double> feeCalculator = (type, currency) -> {
355
if ("premium".equals(type)) return 0.01;
356
if ("USD".equals(currency)) return 0.025;
357
return 0.03;
358
};
359
360
when(mockService.calculateFee(anyString(), anyString()))
361
.thenAnswer(answer(feeCalculator));
362
363
// Error simulation with delays
364
Answer<Void> unreliableService = answersWithDelay(1000,
365
answerVoid((String request) -> {
366
if (request.contains("error")) {
367
throw new ServiceException("Simulated failure");
368
}
369
}));
370
doAnswer(unreliableService).when(mockService).processRequest(anyString());
371
```
372
373
## Import Statements
374
375
To use AdditionalAnswers, include these imports in your test files:
376
377
```java
378
import static org.mockito.AdditionalAnswers.*;
379
import org.mockito.stubbing.Answer1;
380
import org.mockito.stubbing.Answer2;
381
import org.mockito.stubbing.VoidAnswer1;
382
import org.mockito.stubbing.VoidAnswer2;
383
// Import additional Answer3-Answer6 and VoidAnswer3-VoidAnswer6 as needed
384
```
385
386
This provides access to all additional answer methods including `returnsFirstArg`, `returnsSecondArg`, `returnsLastArg`, `returnsArgAt`, `delegatesTo`, `returnsElementsOf`, `answersWithDelay`, and the type-safe `answer`/`answerVoid` methods.
387
388
## Best Practices
389
390
### When to Use Additional Answers
391
392
- **Argument Echoing**: Use `returnsFirstArg`, `returnsSecondArg`, `returnsLastArg`, `returnsArgAt` when the return value should be one of the input parameters
393
- **Partial Mocking**: Use `delegatesTo` for final classes, proxied objects, or when you need most real behavior with selective stubbing
394
- **Sequential Data**: Use `returnsElementsOf` when simulating iterative processes or data streams
395
- **Performance Testing**: Use `answersWithDelay` to simulate network latency, database delays, or slow operations
396
- **Type Safety**: Use `answer`/`answerVoid` with functional interfaces for compile-time type checking and cleaner lambda expressions
397
398
### Performance Considerations
399
400
- `delegatesTo` calls real methods, which may have performance implications or side effects
401
- `answersWithDelay` introduces actual delays in test execution - use judiciously
402
- Functional interface answers have minimal overhead compared to traditional Answer implementations
403
404
### Testing Guidelines
405
406
```java
407
// Good: Clear intent with appropriate answer type
408
when(mockCache.get(anyString())).will(returnsFirstArg()); // Cache returns what you put in
409
410
// Good: Type-safe functional answers
411
Answer1<User, Long> userLoader = id -> userRepository.findById(id);
412
when(mockService.loadUser(anyLong())).thenAnswer(answer(userLoader));
413
414
// Good: Realistic simulation
415
when(mockNetworkService.fetchData())
416
.thenAnswer(answersWithDelay(100, returnsElementsOf(testData)));
417
418
// Avoid: Using delegation when simple stubbing suffices
419
// when(mockList.size()).thenAnswer(delegatesTo(realList)); // Overkill
420
when(mockList.size()).thenReturn(5); // Better
421
```
422
423
### Debugging Tips
424
425
When using complex answers, consider logging or debugging support:
426
427
```java
428
// Add logging to functional answers for debugging
429
Answer1<String, String> debuggingProcessor = input -> {
430
String result = processInput(input);
431
System.out.println("Processed '" + input + "' -> '" + result + "'");
432
return result;
433
};
434
when(mockService.process(anyString())).thenAnswer(answer(debuggingProcessor));
435
```