0
# Private Method Testing
1
2
PowerMock enables stubbing and verification of private method calls, allowing comprehensive testing of internal implementation details when necessary. This capability is essential for testing legacy code where private methods contain critical business logic that cannot be easily extracted.
3
4
## Capabilities
5
6
### Private Instance Method Stubbing by Name
7
8
Stub private instance methods by specifying the method name and arguments.
9
10
```java { .api }
11
static <T> OngoingStubbing<T> when(Object instance, String methodName, Object... arguments) throws Exception;
12
```
13
14
**Parameters:**
15
- `instance` - The object instance containing the private method
16
- `methodName` - Name of the private method to stub
17
- `arguments` - Arguments to match for the method call
18
19
**Returns:** OngoingStubbing for chaining return values or exceptions
20
21
**Usage Example:**
22
```java
23
@Test
24
@PrepareForTest(UserService.class)
25
public void testPrivateMethodStubbing() throws Exception {
26
UserService service = spy(new UserService());
27
28
// Stub private validation method
29
when(service, "validateUser", "john@example.com").thenReturn(true);
30
when(service, "validateUser", "invalid-email").thenReturn(false);
31
32
// Test public method that uses private validation
33
boolean validResult = service.registerUser("john@example.com", "password");
34
boolean invalidResult = service.registerUser("invalid-email", "password");
35
36
assertTrue(validResult);
37
assertFalse(invalidResult);
38
}
39
```
40
41
### Private Instance Method Stubbing by Method Reference
42
43
Stub private instance methods using Method reflection objects for type safety.
44
45
```java { .api }
46
static <T> WithOrWithoutExpectedArguments<T> when(Object instance, Method method) throws Exception;
47
```
48
49
**Parameters:**
50
- `instance` - The object instance containing the private method
51
- `method` - Method reflection object for the private method
52
53
**Returns:** Fluent interface for specifying arguments and return values
54
55
**Usage Example:**
56
```java
57
@Test
58
@PrepareForTest(OrderProcessor.class)
59
public void testPrivateMethodByReflection() throws Exception {
60
OrderProcessor processor = spy(new OrderProcessor());
61
Method validateMethod = OrderProcessor.class.getDeclaredMethod("validateOrder", Order.class);
62
63
// Stub using method reference
64
when(processor, validateMethod).withArguments(any(Order.class)).thenReturn(true);
65
66
Order order = new Order("item1", 100.0);
67
boolean result = processor.processOrder(order);
68
69
assertTrue(result);
70
}
71
```
72
73
### Private Static Method Stubbing
74
75
Stub private static methods on classes using Method reflection.
76
77
```java { .api }
78
static <T> WithOrWithoutExpectedArguments<T> when(Class<?> cls, Method method) throws Exception;
79
```
80
81
**Parameters:**
82
- `cls` - The class containing the private static method
83
- `method` - Method reflection object for the private static method
84
85
**Returns:** Fluent interface for specifying arguments and return values
86
87
**Usage Example:**
88
```java
89
@Test
90
@PrepareForTest(SecurityUtils.class)
91
public void testPrivateStaticMethod() throws Exception {
92
Method encryptMethod = SecurityUtils.class.getDeclaredMethod("encryptInternal", String.class);
93
94
when(SecurityUtils.class, encryptMethod)
95
.withArguments("sensitive")
96
.thenReturn("encrypted-sensitive");
97
98
String result = SecurityUtils.encrypt("sensitive");
99
assertEquals("encrypted-sensitive", result);
100
}
101
```
102
103
### Private Method Stubbing by Parameters
104
105
Stub private methods by providing parameters without specifying the method name, using parameter types for method resolution.
106
107
```java { .api }
108
static <T> OngoingStubbing<T> when(Object instance, Object... arguments) throws Exception;
109
```
110
111
**Parameters:**
112
- `instance` - The object instance containing the private method
113
- `arguments` - Arguments that determine which private method to stub
114
115
**Returns:** OngoingStubbing for chaining return values or exceptions
116
117
**Usage Example:**
118
```java
119
@Test
120
@PrepareForTest(CalculatorService.class)
121
public void testPrivateMethodByParameters() throws Exception {
122
CalculatorService calculator = spy(new CalculatorService());
123
124
// Stub private method based on parameter types and values
125
when(calculator, 5.0, 3.0).thenReturn(8.0); // Assumes private method with (double, double)
126
127
double result = calculator.performComplexCalculation(5.0, 3.0);
128
assertEquals(8.0, result, 0.001);
129
}
130
```
131
132
### Private Static Method Stubbing by Name
133
134
Stub private static methods by specifying the class, method name, and arguments.
135
136
```java { .api }
137
static <T> OngoingStubbing<T> when(Class<?> clazz, String methodToExpect, Object... arguments) throws Exception;
138
```
139
140
**Parameters:**
141
- `clazz` - The class containing the private static method
142
- `methodToExpect` - Name of the private static method to stub
143
- `arguments` - Arguments to match for the method call
144
145
**Returns:** OngoingStubbing for chaining return values or exceptions
146
147
**Usage Example:**
148
```java
149
@Test
150
@PrepareForTest(ConfigurationHelper.class)
151
public void testPrivateStaticMethodByName() throws Exception {
152
when(ConfigurationHelper.class, "loadConfigFromFile", "config.properties")
153
.thenReturn(mockProperties);
154
155
Properties result = ConfigurationHelper.getConfiguration("config.properties");
156
assertEquals(mockProperties, result);
157
}
158
```
159
160
### Private Static Method Stubbing by Parameters
161
162
Stub private static methods using parameter matching without specifying method names.
163
164
```java { .api }
165
static <T> OngoingStubbing<T> when(Class<?> klass, Object... arguments) throws Exception;
166
```
167
168
**Parameters:**
169
- `klass` - The class containing the private static method
170
- `arguments` - Arguments that determine which private static method to stub
171
172
**Returns:** OngoingStubbing for chaining return values or exceptions
173
174
**Usage Example:**
175
```java
176
@Test
177
@PrepareForTest(NetworkUtils.class)
178
public void testPrivateStaticByParams() throws Exception {
179
when(NetworkUtils.class, "192.168.1.1", 8080).thenReturn(true);
180
181
boolean isReachable = NetworkUtils.checkConnection("192.168.1.1", 8080);
182
assertTrue(isReachable);
183
}
184
```
185
186
### Standard Mockito Delegation
187
188
Delegates to standard Mockito when() for regular (non-private) method stubbing within PowerMock tests.
189
190
```java { .api }
191
static <T> OngoingStubbing<T> when(T methodCall);
192
```
193
194
**Parameters:**
195
- `methodCall` - The method call to stub (standard Mockito syntax)
196
197
**Returns:** OngoingStubbing for chaining return values or exceptions
198
199
**Usage Example:**
200
```java
201
@Test
202
@PrepareForTest(DatabaseService.class)
203
public void testCombinedStubbing() throws Exception {
204
DatabaseService service = spy(new DatabaseService());
205
Connection mockConnection = mock(Connection.class);
206
207
// Standard Mockito stubbing for public methods
208
when(service.getConnection()).thenReturn(mockConnection);
209
210
// PowerMock stubbing for private methods
211
when(service, "validateConnection", mockConnection).thenReturn(true);
212
213
boolean result = service.performQuery("SELECT * FROM users");
214
assertTrue(result);
215
}
216
```
217
218
### Private Method Verification
219
220
Verify that private methods were called with expected arguments and frequencies.
221
222
```java { .api }
223
static PrivateMethodVerification verifyPrivate(Object object) throws Exception;
224
static PrivateMethodVerification verifyPrivate(Object object, VerificationMode verificationMode) throws Exception;
225
static PrivateMethodVerification verifyPrivate(Class<?> clazz) throws Exception;
226
static PrivateMethodVerification verifyPrivate(Class<?> clazz, VerificationMode verificationMode) throws Exception;
227
```
228
229
**Parameters:**
230
- `object`/`clazz` - The instance or class containing the private method
231
- `verificationMode` - Verification mode (times, atLeast, never, etc.)
232
233
**Returns:** PrivateMethodVerification for specifying the method to verify
234
235
**Usage Example:**
236
```java
237
@Test
238
@PrepareForTest(EmailService.class)
239
public void testPrivateMethodVerification() throws Exception {
240
EmailService service = spy(new EmailService());
241
242
service.sendWelcomeEmail("user@example.com");
243
244
// Verify private method was called
245
verifyPrivate(service).invoke("validateEmailFormat", "user@example.com");
246
verifyPrivate(service, times(1)).invoke("logEmailActivity", anyString());
247
}
248
```
249
250
## Verification Interface Methods
251
252
```java { .api }
253
interface PrivateMethodVerification {
254
void invoke(Object... arguments) throws Exception;
255
WithOrWithoutVerifiedArguments invoke(Method method) throws Exception;
256
void invoke(String methodToVerify, Object... arguments) throws Exception;
257
}
258
```
259
260
## Common Patterns
261
262
### Testing Private Business Logic
263
264
```java
265
@Test
266
@PrepareForTest(LoanCalculator.class)
267
public void testPrivateBusinessLogic() throws Exception {
268
LoanCalculator calculator = spy(new LoanCalculator());
269
270
// Stub private risk assessment method
271
when(calculator, "assessCreditRisk", any(CreditProfile.class)).thenReturn(RiskLevel.LOW);
272
273
CreditProfile profile = new CreditProfile(750, 50000, 5000);
274
LoanOffer offer = calculator.calculateLoanOffer(profile);
275
276
// Verify the private method was used in calculation
277
verifyPrivate(calculator).invoke("assessCreditRisk", profile);
278
assertEquals(5.5, offer.getInterestRate(), 0.1);
279
}
280
```
281
282
### Testing Private Validation Methods
283
284
```java
285
@Test
286
@PrepareForTest(PasswordValidator.class)
287
public void testPrivateValidation() throws Exception {
288
PasswordValidator validator = spy(new PasswordValidator());
289
290
// Test each private validation rule separately
291
when(validator, "checkLength", "short").thenReturn(false);
292
when(validator, "checkComplexity", "simple123").thenReturn(false);
293
when(validator, "checkLength", "properLength123!").thenReturn(true);
294
when(validator, "checkComplexity", "properLength123!").thenReturn(true);
295
296
boolean weakResult = validator.isValidPassword("short");
297
boolean strongResult = validator.isValidPassword("properLength123!");
298
299
assertFalse(weakResult);
300
assertTrue(strongResult);
301
302
verifyPrivate(validator).invoke("checkLength", "short");
303
verifyPrivate(validator).invoke("checkComplexity", "properLength123!");
304
}
305
```
306
307
### Testing Private Error Handling
308
309
```java
310
@Test
311
@PrepareForTest(DataProcessor.class)
312
public void testPrivateErrorHandling() throws Exception {
313
DataProcessor processor = spy(new DataProcessor());
314
315
// Stub private error recovery method
316
when(processor, "recoverFromError", any(Exception.class)).thenReturn("recovered-data");
317
318
// Test error scenario triggers private recovery
319
String result = processor.processData("corrupted-input");
320
321
assertEquals("recovered-data", result);
322
verifyPrivate(processor).invoke("recoverFromError", any(ProcessingException.class));
323
}
324
```
325
326
## Requirements
327
328
- Classes with private methods must be specified in `@PrepareForTest` annotation
329
- Test must use `@RunWith(PowerMockRunner.class)` or equivalent
330
- Private method testing requires spying on real objects or classes
331
- Method names and parameter types must match exactly for successful stubbing
332
- Private static methods require class-level mocking setup