0
# Advanced Stubbing
1
2
PowerMock provides enhanced stubbing capabilities that extend beyond standard Mockito when() syntax. These methods are essential for stubbing void methods, private methods, static methods, and scenarios where the standard approach cannot be used due to Java language limitations.
3
4
## Capabilities
5
6
### Custom Answer Stubbing
7
8
Stub methods with custom Answer implementations for complex return logic or side effects.
9
10
```java { .api }
11
static PowerMockitoStubber doAnswer(Answer<?> answer);
12
```
13
14
**Parameters:**
15
- `answer` - Custom Answer implementation defining the method behavior
16
17
**Returns:** PowerMockitoStubber for chaining with method selection
18
19
**Usage Example:**
20
```java
21
@Test
22
@PrepareForTest(DatabaseService.class)
23
public void testCustomAnswer() throws Exception {
24
DatabaseService service = spy(new DatabaseService());
25
26
doAnswer(new Answer<String>() {
27
@Override
28
public String answer(InvocationOnMock invocation) throws Throwable {
29
Object[] args = invocation.getArguments();
30
String query = (String) args[0];
31
return "Result for: " + query.toUpperCase();
32
}
33
}).when(service, "executeQuery", anyString());
34
35
String result = service.performSearch("select * from users");
36
assertEquals("Result for: SELECT * FROM USERS", result);
37
}
38
```
39
40
### Exception Stubbing
41
42
Stub methods to throw specific exceptions, particularly useful for void methods and error scenario testing.
43
44
```java { .api }
45
static PowerMockitoStubber doThrow(Throwable toBeThrown);
46
```
47
48
**Parameters:**
49
- `toBeThrown` - The exception to throw when the stubbed method is called
50
51
**Returns:** PowerMockitoStubber for chaining with method selection
52
53
**Usage Example:**
54
```java
55
@Test
56
@PrepareForTest(FileManager.class)
57
public void testExceptionStubbing() throws Exception {
58
FileManager manager = spy(new FileManager());
59
60
// Stub private method to throw exception
61
doThrow(new IOException("Disk full")).when(manager, "writeToFile", anyString(), anyString());
62
63
// Test that exception is properly handled
64
assertThrows(FileOperationException.class, () -> {
65
manager.saveDocument("document.txt", "content");
66
});
67
}
68
```
69
70
### Real Method Call Stubbing
71
72
Stub methods to call their real implementation, useful for partial mocking scenarios.
73
74
```java { .api }
75
static PowerMockitoStubber doCallRealMethod();
76
```
77
78
**Returns:** PowerMockitoStubber for chaining with method selection
79
80
**Usage Example:**
81
```java
82
@Test
83
@PrepareForTest(MathUtils.class)
84
public void testCallRealMethod() {
85
mockStatic(MathUtils.class);
86
87
// Mock one method but call real implementation for others
88
when(MathUtils.complexCalculation(anyDouble())).thenReturn(100.0);
89
doCallRealMethod().when(MathUtils.class);
90
MathUtils.simpleAddition(5, 3);
91
92
assertEquals(100.0, MathUtils.complexCalculation(50.0), 0.001);
93
assertEquals(8, MathUtils.simpleAddition(5, 3)); // Real implementation
94
}
95
```
96
97
### Do Nothing Stubbing
98
99
Stub void methods to do nothing, overriding default behavior or consecutive call stubbing.
100
101
```java { .api }
102
static PowerMockitoStubber doNothing();
103
```
104
105
**Returns:** PowerMockitoStubber for chaining with method selection
106
107
**Usage Example:**
108
```java
109
@Test
110
@PrepareForTest(Logger.class)
111
public void testDoNothing() throws Exception {
112
Logger logger = spy(new Logger());
113
114
// Stub private void method to do nothing
115
doNothing().when(logger, "writeToFile", anyString());
116
117
// First call does nothing, second call throws exception
118
doNothing().doThrow(new IOException("File locked")).when(logger, "writeToFile", anyString());
119
120
logger.log("First message"); // Does nothing
121
122
assertThrows(IOException.class, () -> {
123
logger.log("Second message"); // Throws exception
124
});
125
}
126
```
127
128
### Return Value Stubbing
129
130
Stub methods to return specific values, particularly useful when when() syntax cannot be used.
131
132
```java { .api }
133
static PowerMockitoStubber doReturn(Object toBeReturned);
134
static PowerMockitoStubber doReturn(Object toBeReturned, Object... othersToBeReturned);
135
```
136
137
**Parameters:**
138
- `toBeReturned` - The value to return when the stubbed method is called
139
- `othersToBeReturned` - Additional values for consecutive calls
140
141
**Returns:** PowerMockitoStubber for chaining with method selection
142
143
**Usage Example:**
144
```java
145
@Test
146
@PrepareForTest(ConfigurationManager.class)
147
public void testDoReturn() throws Exception {
148
ConfigurationManager manager = spy(new ConfigurationManager());
149
150
// Use doReturn when when() would call the real method
151
doReturn("mocked-value").when(manager, "getConfigValue", "key");
152
153
// Multiple return values for consecutive calls
154
doReturn("first", "second", "third").when(manager, "getNextValue");
155
156
assertEquals("mocked-value", manager.getProperty("key"));
157
assertEquals("first", manager.getNext());
158
assertEquals("second", manager.getNext());
159
assertEquals("third", manager.getNext());
160
}
161
```
162
163
## PowerMockitoStubber Interface Methods
164
165
The PowerMockitoStubber interface extends Mockito's Stubber with additional capabilities for static and private methods:
166
167
```java { .api }
168
interface PowerMockitoStubber extends Stubber {
169
void when(Class<?> classMock);
170
<T> PrivatelyExpectedArguments when(T mock, Method method) throws Exception;
171
<T> void when(T mock, Object... arguments) throws Exception;
172
<T> void when(T mock, String methodToExpected, Object... arguments) throws Exception;
173
<T> PrivatelyExpectedArguments when(Class<T> classMock, Method method) throws Exception;
174
<T> void when(Class<T> classMock, Object... arguments) throws Exception;
175
<T> void when(Class<T> classMock, String methodToExpected, Object... parameters) throws Exception;
176
}
177
```
178
179
## Common Patterns
180
181
### Stubbing Static Void Methods
182
183
```java
184
@Test
185
@PrepareForTest(SystemLogger.class)
186
public void testStaticVoidMethodStubbing() {
187
mockStatic(SystemLogger.class);
188
189
// Stub static void method to throw exception
190
doThrow(new RuntimeException("Logging failed")).when(SystemLogger.class);
191
SystemLogger.log(eq("ERROR"), anyString());
192
193
ServiceManager manager = new ServiceManager();
194
195
assertThrows(ServiceException.class, () -> {
196
manager.handleError("Critical error occurred");
197
});
198
}
199
```
200
201
### Consecutive Behavior Stubbing
202
203
```java
204
@Test
205
@PrepareForTest(NetworkService.class)
206
public void testConsecutiveBehavior() throws Exception {
207
NetworkService service = spy(new NetworkService());
208
209
// First call succeeds, second fails, third succeeds again
210
doReturn("success")
211
.doThrow(new NetworkException("Connection timeout"))
212
.doReturn("retry success")
213
.when(service, "attemptConnection", anyString());
214
215
assertEquals("success", service.connect("server1"));
216
assertThrows(NetworkException.class, () -> service.connect("server1"));
217
assertEquals("retry success", service.connect("server1"));
218
}
219
```
220
221
### Stubbing Private Methods with Complex Logic
222
223
```java
224
@Test
225
@PrepareForTest(DataProcessor.class)
226
public void testComplexPrivateMethodStubbing() throws Exception {
227
DataProcessor processor = spy(new DataProcessor());
228
229
doAnswer(invocation -> {
230
String data = (String) invocation.getArguments()[0];
231
if (data.startsWith("PRIORITY")) {
232
return data.toUpperCase();
233
} else {
234
return data.toLowerCase();
235
}
236
}).when(processor, "transformData", anyString());
237
238
String priorityResult = processor.processData("PRIORITY: urgent message");
239
String normalResult = processor.processData("Normal message");
240
241
assertEquals("PRIORITY: URGENT MESSAGE", priorityResult);
242
assertEquals("normal message", normalResult);
243
}
244
```
245
246
### Stubbing with Side Effects
247
248
```java
249
@Test
250
@PrepareForTest(CacheManager.class)
251
public void testSideEffects() throws Exception {
252
CacheManager manager = spy(new CacheManager());
253
AtomicInteger callCount = new AtomicInteger(0);
254
255
doAnswer(invocation -> {
256
callCount.incrementAndGet();
257
String key = (String) invocation.getArguments()[0];
258
return "cached-" + key + "-" + callCount.get();
259
}).when(manager, "getCachedValue", anyString());
260
261
String first = manager.getValue("key1");
262
String second = manager.getValue("key2");
263
264
assertEquals("cached-key1-1", first);
265
assertEquals("cached-key2-2", second);
266
assertEquals(2, callCount.get());
267
}
268
```
269
270
### Mixed Stubbing Approaches
271
272
```java
273
@Test
274
@PrepareForTest(SecurityService.class)
275
public void testMixedStubbing() throws Exception {
276
SecurityService service = spy(new SecurityService());
277
278
// Use when() for return values
279
when(service.validateUser("admin")).thenReturn(true);
280
281
// Use doThrow for exceptions
282
doThrow(new SecurityException("Access denied")).when(service, "checkPermissions", "guest");
283
284
// Use doNothing for void methods
285
doNothing().when(service, "logSecurityEvent", anyString());
286
287
// Use doAnswer for complex logic
288
doAnswer(invocation -> {
289
String action = (String) invocation.getArguments()[0];
290
return "audit-" + action + "-" + System.currentTimeMillis();
291
}).when(service, "generateAuditId", anyString());
292
293
assertTrue(service.validateUser("admin"));
294
assertThrows(SecurityException.class, () -> service.authorize("guest", "read"));
295
String auditId = service.performAction("login");
296
assertTrue(auditId.startsWith("audit-login-"));
297
}
298
```
299
300
## When to Use Advanced Stubbing
301
302
### Use doAnswer() when:
303
- Complex return logic based on input parameters
304
- Side effects need to be performed during method execution
305
- Method behavior depends on object state or external conditions
306
307
### Use doThrow() when:
308
- Stubbing void methods to throw exceptions
309
- Testing error handling and exception propagation
310
- Simulating failure scenarios in dependencies
311
312
### Use doCallRealMethod() when:
313
- Partial mocking where most methods should use real implementation
314
- Testing method interactions while stubbing only specific behaviors
315
- Gradual refactoring where some methods are mocked temporarily
316
317
### Use doNothing() when:
318
- Overriding default behavior of void methods
319
- Consecutive stubbing where some calls should be ignored
320
- Disabling side effects like logging or notifications in tests
321
322
### Use doReturn() when:
323
- Standard when() syntax would call the real method (spies)
324
- Overriding previous exception stubbing
325
- Type safety issues with generic return types
326
327
## Requirements
328
329
- Enhanced stubbing works with both static and instance methods
330
- Classes with stubbed methods must be specified in `@PrepareForTest` annotation
331
- Test must use `@RunWith(PowerMockRunner.class)` or equivalent
332
- Stubbing must be configured before the code under test executes
333
- PowerMockitoStubber chaining must be completed with appropriate when() method call