0
# Method Stubbing and Behavior
1
2
This section covers configuring mock object behavior through stubbing, including return values, exceptions, custom answers, and consecutive calls.
3
4
## Basic Stubbing
5
6
### When-Then Stubbing
7
8
Configure method behavior using the when().then...() pattern.
9
10
```java { .api }
11
public static <T> OngoingStubbing<T> when(T methodCall)
12
13
interface OngoingStubbing<T> {
14
OngoingStubbing<T> thenReturn(T value);
15
OngoingStubbing<T> thenReturn(T value, T... values);
16
OngoingStubbing<T> thenThrow(Throwable... throwables);
17
OngoingStubbing<T> thenThrow(Class<? extends Throwable> throwableType);
18
OngoingStubbing<T> thenThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown);
19
OngoingStubbing<T> thenCallRealMethod();
20
OngoingStubbing<T> thenAnswer(Answer<?> answer);
21
T getMock();
22
}
23
```
24
25
**Usage Examples:**
26
27
```java
28
List<String> mockList = mock(List.class);
29
30
// Return specific value
31
when(mockList.get(0)).thenReturn("first");
32
when(mockList.size()).thenReturn(1);
33
34
// Return consecutive values
35
when(mockList.get(anyInt()))
36
.thenReturn("first")
37
.thenReturn("second")
38
.thenReturn("third");
39
40
// Alternative syntax for consecutive values
41
when(mockList.get(anyInt())).thenReturn("first", "second", "third");
42
43
// Throw exception
44
when(mockList.get(999)).thenThrow(new IndexOutOfBoundsException());
45
when(mockList.clear()).thenThrow(UnsupportedOperationException.class);
46
```
47
48
## Do-Family Stubbing
49
50
### Do-When Stubbing
51
52
Alternative stubbing syntax, especially useful for void methods and spies.
53
54
```java { .api }
55
public static Stubber doReturn(Object toBeReturned)
56
public static Stubber doReturn(Object toBeReturned, Object... toBeReturnedNext)
57
public static Stubber doThrow(Throwable... toBeThrown)
58
public static Stubber doThrow(Class<? extends Throwable> toBeThrown)
59
public static Stubber doThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... toBeThrownNext)
60
public static Stubber doAnswer(Answer answer)
61
public static Stubber doNothing()
62
public static Stubber doCallRealMethod()
63
64
interface Stubber {
65
<T> T when(T mock);
66
Stubber doReturn(Object toBeReturned);
67
Stubber doReturn(Object toBeReturned, Object... toBeReturnedNext);
68
Stubber doThrow(Throwable... toBeThrown);
69
Stubber doThrow(Class<? extends Throwable> toBeThrown);
70
Stubber doAnswer(Answer answer);
71
Stubber doNothing();
72
Stubber doCallRealMethod();
73
}
74
```
75
76
**Usage Examples:**
77
78
```java
79
List<String> mockList = mock(List.class);
80
81
// Stub void method
82
doNothing().when(mockList).clear();
83
doThrow(new RuntimeException()).when(mockList).clear();
84
85
// Useful for spies (avoids calling real method)
86
List<String> spy = spy(new ArrayList<>());
87
doReturn("stubbed").when(spy).get(0); // doesn't call real get()
88
89
// Chain multiple behaviors
90
doReturn("first")
91
.doReturn("second")
92
.doThrow(new RuntimeException())
93
.when(mockList).get(anyInt());
94
```
95
96
## Custom Answers
97
98
### Answer Interface
99
100
Provide custom logic for method invocations.
101
102
```java { .api }
103
interface Answer<T> {
104
T answer(InvocationOnMock invocation) throws Throwable;
105
}
106
107
interface InvocationOnMock {
108
Object getMock();
109
Method getMethod();
110
Object[] getArguments();
111
<T> T getArgument(int index);
112
<T> T getArgument(int index, Class<T> clazz);
113
Object callRealMethod() throws Throwable;
114
}
115
```
116
117
**Usage Examples:**
118
119
```java
120
List<String> mockList = mock(List.class);
121
122
// Custom answer with access to arguments
123
when(mockList.get(anyInt())).thenAnswer(invocation -> {
124
int index = invocation.getArgument(0);
125
return "element-" + index;
126
});
127
128
// Answer that calls real method with modified arguments
129
UserService spy = spy(new UserService());
130
when(spy.findUser(anyString())).thenAnswer(invocation -> {
131
String name = invocation.getArgument(0);
132
return invocation.callRealMethod(name.toLowerCase());
133
});
134
135
// Answer using lambda for simple cases
136
when(mockList.size()).thenAnswer(inv -> 42);
137
```
138
139
### Typed Answers
140
141
Type-safe answer interfaces for methods with specific parameter counts.
142
143
```java { .api }
144
interface Answer1<T, A0> {
145
T answer(A0 argument0) throws Throwable;
146
}
147
148
interface Answer2<T, A0, A1> {
149
T answer(A0 argument0, A1 argument1) throws Throwable;
150
}
151
152
interface VoidAnswer1<A0> {
153
void answer(A0 argument0) throws Throwable;
154
}
155
// ... up to Answer6 and VoidAnswer6
156
```
157
158
**Usage Examples:**
159
160
```java
161
UserService mockService = mock(UserService.class);
162
163
// Type-safe answer
164
Answer1<User, String> userFinder = name -> new User(name);
165
when(mockService.findUser(anyString())).thenAnswer(userFinder);
166
167
// Void answer
168
VoidAnswer1<String> logger = message -> System.out.println("Log: " + message);
169
doAnswer(logger).when(mockService).log(anyString());
170
```
171
172
## Advanced Stubbing
173
174
### Lenient Stubbing
175
176
Bypass strict stubbing validation for specific stubs.
177
178
```java { .api }
179
public static LenientStubber lenient()
180
181
interface LenientStubber extends Stubber {
182
// Same methods as Stubber
183
}
184
```
185
186
**Usage Example:**
187
188
```java
189
// Lenient stubbing won't fail on unused stubs
190
lenient().when(mockList.get(0)).thenReturn("first");
191
lenient().when(mockList.get(1)).thenReturn("second");
192
// Even if get(1) is never called, test won't fail
193
```
194
195
### Consecutive Calls
196
197
Configure different behaviors for consecutive method calls.
198
199
**Usage Examples:**
200
201
```java
202
// Using thenReturn with multiple values
203
when(mockList.get(0))
204
.thenReturn("first")
205
.thenReturn("second")
206
.thenThrow(new RuntimeException());
207
208
// Using doReturn chain
209
doReturn("first")
210
.doReturn("second")
211
.doThrow(new RuntimeException())
212
.when(mockList).get(0);
213
214
// Iterator-style stubbing
215
when(mockIterator.hasNext())
216
.thenReturn(true)
217
.thenReturn(true)
218
.thenReturn(false);
219
```
220
221
### Argument-Dependent Stubbing
222
223
Different behavior based on method arguments.
224
225
**Usage Examples:**
226
227
```java
228
Map<String, String> mockMap = mock(Map.class);
229
230
// Different returns for different arguments
231
when(mockMap.get("key1")).thenReturn("value1");
232
when(mockMap.get("key2")).thenReturn("value2");
233
when(mockMap.get(argThat(key -> key.startsWith("error"))))
234
.thenThrow(new IllegalArgumentException());
235
236
// Using argument matchers
237
when(mockMap.get(anyString())).thenReturn("default");
238
when(mockMap.get(startsWith("special"))).thenReturn("special-value");
239
```
240
241
## Stubbing Verification
242
243
### Stubbing Information
244
245
Access information about configured stubs.
246
247
```java { .api }
248
interface StubbingInfo {
249
InvocationOnMock getInvocation();
250
boolean wasUsed();
251
}
252
```
253
254
**Usage Example:**
255
256
```java
257
List<String> mockList = mock(List.class);
258
when(mockList.get(0)).thenReturn("stubbed");
259
260
MockingDetails details = mockingDetails(mockList);
261
Collection<StubbingInfo> stubbings = details.getStubbings();
262
263
for (StubbingInfo stub : stubbings) {
264
System.out.println("Stub used: " + stub.wasUsed());
265
}
266
```