0
# Annotation-Based Configuration
1
2
PowerMock provides annotation-based configuration that simplifies mock setup and reduces boilerplate code. This declarative approach improves test readability and maintainability while providing automatic mock lifecycle management.
3
4
## Capabilities
5
6
### Basic Mock Annotation
7
8
Automatically create and inject mock objects using field annotations.
9
10
```java { .api }
11
/**
12
* Annotation for automatic mock creation and injection.
13
* Can be placed on fields to eliminate manual mock setup.
14
*/
15
@Target({ElementType.FIELD})
16
@Retention(RetentionPolicy.RUNTIME)
17
@Documented
18
public @interface Mock {
19
/**
20
* Method names to mock for partial mocking.
21
* If empty, all methods are mocked.
22
*/
23
String[] value() default "";
24
25
/**
26
* Specific field name for targeted mock injection.
27
* When set, mock will be assigned to the given field name in test subjects.
28
*/
29
String fieldName() default "";
30
}
31
```
32
33
#### Usage Example
34
35
```java
36
import org.powermock.api.easymock.annotation.Mock;
37
import org.powermock.api.extension.listener.AnnotationEnabler;
38
import org.powermock.core.classloader.annotations.PowerMockListener;
39
40
@PowerMockListener(AnnotationEnabler.class)
41
public class BasicAnnotationTest {
42
43
@Mock
44
private UserService userService;
45
46
@Mock
47
private OrderService orderService;
48
49
private ShoppingCart shoppingCart;
50
51
@Before
52
public void setUp() {
53
shoppingCart = new ShoppingCart(userService, orderService);
54
}
55
56
@Test
57
public void testAnnotationBasedMocks() {
58
// Mocks are automatically created and available
59
expect(userService.getCurrentUser()).andReturn(new User("john"));
60
expect(orderService.getPendingOrders("john")).andReturn(Arrays.asList(new Order("order1")));
61
62
PowerMock.replayAll();
63
64
List<Order> orders = shoppingCart.getUserOrders();
65
66
assertEquals(1, orders.size());
67
assertEquals("order1", orders.get(0).getId());
68
69
PowerMock.verifyAll();
70
}
71
}
72
```
73
74
### Strict Mock Annotation
75
76
Create strict mocks that verify method call order using annotations.
77
78
```java { .api }
79
/**
80
* Annotation for automatic strict mock creation.
81
* Strict mocks check the order of method calls.
82
*/
83
@Target({ElementType.FIELD})
84
@Retention(RetentionPolicy.RUNTIME)
85
@Documented
86
@Inherited
87
public @interface MockStrict {
88
/**
89
* Method names to mock for partial mocking.
90
* If empty, all methods are mocked.
91
*/
92
String[] value() default "";
93
}
94
```
95
96
#### Usage Example
97
98
```java
99
@PowerMockListener(AnnotationEnabler.class)
100
public class StrictAnnotationTest {
101
102
@MockStrict
103
private DatabaseConnection connection;
104
105
@MockStrict
106
private Logger logger;
107
108
private DataProcessor processor;
109
110
@Before
111
public void setUp() {
112
processor = new DataProcessor(connection, logger);
113
}
114
115
@Test
116
public void testStrictMockAnnotations() {
117
// Strict mocks verify exact order of calls
118
expect(logger.info("Starting connection")).andReturn(true);
119
expect(connection.connect()).andReturn(true);
120
expect(connection.executeQuery("SELECT * FROM data")).andReturn("data");
121
expect(logger.info("Connection completed")).andReturn(true);
122
expect(connection.disconnect()).andReturn(true);
123
124
PowerMock.replayAll();
125
126
// These calls must happen in exactly this order
127
String result = processor.processData();
128
129
assertEquals("Processed: data", result);
130
PowerMock.verifyAll();
131
}
132
}
133
```
134
135
### Nice Mock Annotation
136
137
Create nice mocks that provide default return values for unexpected calls.
138
139
```java { .api }
140
/**
141
* Annotation for automatic nice mock creation.
142
* Nice mocks allow unexpected method calls and return appropriate default values.
143
*/
144
@Target({ElementType.FIELD})
145
@Retention(RetentionPolicy.RUNTIME)
146
@Documented
147
@Inherited
148
public @interface MockNice {
149
/**
150
* Method names to mock for partial mocking.
151
* If empty, all methods are mocked.
152
*/
153
String[] value() default "";
154
}
155
```
156
157
#### Usage Example
158
159
```java
160
@PowerMockListener(AnnotationEnabler.class)
161
public class NiceAnnotationTest {
162
163
@MockNice
164
private ConfigurationService configService;
165
166
@MockNice
167
private Logger logger;
168
169
private ApplicationService appService;
170
171
@Before
172
public void setUp() {
173
appService = new ApplicationService(configService, logger);
174
}
175
176
@Test
177
public void testNiceMockAnnotations() {
178
// Only set up the expectations you care about
179
expect(configService.getProperty("app.name")).andReturn("TestApp");
180
181
PowerMock.replayAll();
182
183
// This call has explicit expectation
184
String appName = appService.getApplicationName();
185
assertEquals("TestApp", appName);
186
187
// These calls don't have expectations but work with nice mocks
188
appService.logStartup(); // logger methods return void (default)
189
String version = appService.getVersion(); // Returns null (default for String)
190
191
PowerMock.verifyAll();
192
}
193
}
194
```
195
196
## Partial Mocking with Annotations
197
198
### Method-Specific Partial Mocking
199
200
Use annotations to create partial mocks that only mock specific methods.
201
202
```java
203
@PowerMockListener(AnnotationEnabler.class)
204
public class PartialMockAnnotationTest {
205
206
// Only mock the sendEmail and logEmailSent methods
207
@Mock({"sendEmail", "logEmailSent"})
208
private EmailService emailService;
209
210
// Only mock the validateInput method
211
@MockStrict({"validateInput"})
212
private InputValidator validator;
213
214
@Test
215
public void testPartialMockingWithAnnotations() {
216
// Set up expectations for mocked methods only
217
expect(validator.validateInput("test input")).andReturn(true);
218
expect(emailService.sendEmail("test@example.com", "Subject", "Body")).andReturn(true);
219
emailService.logEmailSent("test@example.com");
220
PowerMock.expectLastCall();
221
222
PowerMock.replayAll();
223
224
// Mocked methods
225
boolean isValid = validator.validateInput("test input");
226
boolean sent = emailService.sendEmail("test@example.com", "Subject", "Body");
227
emailService.logEmailSent("test@example.com");
228
229
// Non-mocked methods use real implementation
230
String formatted = validator.formatInput("test input"); // Real behavior
231
String serverInfo = emailService.getServerInfo(); // Real behavior
232
233
assertTrue(isValid);
234
assertTrue(sent);
235
assertNotNull(formatted);
236
assertNotNull(serverInfo);
237
238
PowerMock.verifyAll();
239
}
240
}
241
```
242
243
### Field Name Targeting
244
245
Use the `fieldName` attribute to control mock injection into specific fields.
246
247
```java
248
public class TestSubject {
249
private UserService primaryUserService;
250
private UserService backupUserService;
251
private OrderService orderService;
252
}
253
254
@PowerMockListener(AnnotationEnabler.class)
255
public class FieldTargetingTest {
256
257
// Inject into primaryUserService field specifically
258
@Mock(fieldName = "primaryUserService")
259
private UserService mockPrimaryUserService;
260
261
// Inject into backupUserService field specifically
262
@Mock(fieldName = "backupUserService")
263
private UserService mockBackupUserService;
264
265
@Mock
266
private OrderService orderService;
267
268
@TestSubject
269
private TestSubject testSubject;
270
271
@Test
272
public void testFieldNameTargeting() {
273
// Set up different behaviors for different UserService instances
274
expect(mockPrimaryUserService.getUserById(1)).andReturn(new User("primary-user"));
275
expect(mockBackupUserService.getUserById(1)).andReturn(new User("backup-user"));
276
expect(orderService.getOrdersByUser(1)).andReturn(Arrays.asList(new Order("order1")));
277
278
PowerMock.replayAll();
279
280
// testSubject now has different mocks injected into specific fields
281
String result = testSubject.processUserWithBackup(1);
282
283
assertTrue(result.contains("primary-user"));
284
assertTrue(result.contains("backup-user"));
285
286
PowerMock.verifyAll();
287
}
288
}
289
```
290
291
## Advanced Annotation Patterns
292
293
### Combining Annotation Types
294
295
Mix different annotation types in the same test class for complex scenarios.
296
297
```java
298
@PowerMockListener(AnnotationEnabler.class)
299
public class MixedAnnotationTest {
300
301
@Mock
302
private UserService userService; // Regular mock
303
304
@MockStrict
305
private DatabaseConnection connection; // Strict mock
306
307
@MockNice
308
private Logger logger; // Nice mock
309
310
@Mock({"validatePermissions"})
311
private SecurityService securityService; // Partial mock
312
313
@Test
314
public void testMixedAnnotationTypes() {
315
// Set up expectations based on mock types
316
expect(userService.getUserById(1)).andReturn(new User("test"));
317
318
// Strict mock - order matters
319
expect(connection.connect()).andReturn(true);
320
expect(connection.executeQuery(anyString())).andReturn("data");
321
expect(connection.disconnect()).andReturn(true);
322
323
// Partial mock - only mocked method needs expectation
324
expect(securityService.validatePermissions("test", "read")).andReturn(true);
325
326
// Nice mock - no explicit expectations needed
327
328
PowerMock.replayAll();
329
330
// Test code uses all mock types
331
MyService service = new MyService(userService, connection, logger, securityService);
332
String result = service.processUserData(1);
333
334
assertNotNull(result);
335
PowerMock.verifyAll();
336
}
337
}
338
```
339
340
### Annotation with Static and Constructor Mocking
341
342
Combine annotations with programmatic static and constructor mocking.
343
344
```java
345
@PowerMockListener(AnnotationEnabler.class)
346
@PrepareForTest({FileUtils.class, DatabaseConnection.class})
347
public class HybridAnnotationTest {
348
349
@Mock
350
private UserService userService;
351
352
@MockStrict
353
private Logger logger;
354
355
@Test
356
public void testAnnotationsWithStaticMocking() throws Exception {
357
// Annotation-based mocks
358
expect(userService.getUserById(1)).andReturn(new User("test"));
359
expect(logger.info("Processing user")).andReturn(true);
360
361
// Programmatic static mocking
362
PowerMock.mockStatic(FileUtils.class);
363
expect(FileUtils.readFile("config.txt")).andReturn("config data");
364
365
// Programmatic constructor mocking
366
DatabaseConnection mockConnection = PowerMock.createMock(DatabaseConnection.class);
367
PowerMock.expectNew(DatabaseConnection.class, "localhost").andReturn(mockConnection);
368
expect(mockConnection.connect()).andReturn(true);
369
370
PowerMock.replayAll();
371
372
// Test code using both annotation and programmatic mocks
373
HybridService service = new HybridService(userService, logger);
374
String result = service.processUserWithConfig(1);
375
376
assertNotNull(result);
377
PowerMock.verifyAll();
378
}
379
}
380
```
381
382
## Configuration and Setup
383
384
### Required Dependencies
385
386
Ensure proper annotation processing dependencies are available:
387
388
```xml
389
<dependency>
390
<groupId>org.powermock</groupId>
391
<artifactId>powermock-api-easymock</artifactId>
392
<version>2.0.9</version>
393
<scope>test</scope>
394
</dependency>
395
```
396
397
### Test Class Configuration
398
399
Always include the `@PowerMockListener(AnnotationEnabler.class)` annotation:
400
401
```java
402
@RunWith(PowerMockRunner.class) // If using JUnit 4
403
@PowerMockListener(AnnotationEnabler.class) // Required for annotation processing
404
@PrepareForTest({ClassesWithStaticMethods.class}) // If using static mocking
405
public class AnnotationConfiguredTest {
406
// Test implementation
407
}
408
```
409
410
### TestNG Configuration
411
412
For TestNG, use the PowerMock TestNG listener:
413
414
```java
415
@PowerMockListener(AnnotationEnabler.class)
416
public class TestNGAnnotationTest extends PowerMockTestCase {
417
418
@Mock
419
private UserService userService;
420
421
@Test
422
public void testWithTestNG() {
423
expect(userService.getUserById(1)).andReturn(new User("testng-user"));
424
PowerMock.replayAll();
425
426
// Test implementation
427
428
PowerMock.verifyAll();
429
}
430
}
431
```
432
433
## Best Practices
434
435
### Annotation Organization
436
437
```java
438
@PowerMockListener(AnnotationEnabler.class)
439
public class WellOrganizedAnnotationTest {
440
441
// Group related mocks together
442
// Core service mocks
443
@Mock private UserService userService;
444
@Mock private OrderService orderService;
445
446
// Infrastructure mocks
447
@MockStrict private DatabaseConnection connection;
448
@MockNice private Logger logger;
449
450
// Partial mocks for complex services
451
@Mock({"validate", "transform"})
452
private DataProcessor dataProcessor;
453
454
// Test subjects
455
@TestSubject
456
private ApplicationService applicationService;
457
458
@Test
459
public void testWellOrganized() {
460
// Clear test implementation
461
}
462
}
463
```
464
465
### Mock Lifecycle Management
466
467
```java
468
@PowerMockListener(AnnotationEnabler.class)
469
public class MockLifecycleTest {
470
471
@Mock private UserService userService;
472
@MockStrict private AuditLogger auditLogger;
473
474
@Before
475
public void setUpMocks() {
476
// Additional setup after annotation processing
477
// Mocks are already created by annotations
478
}
479
480
@After
481
public void tearDownMocks() {
482
// PowerMock automatically handles cleanup
483
// Manual cleanup only if needed for special cases
484
PowerMock.resetAll();
485
}
486
487
@Test
488
public void testWithLifecycleManagement() {
489
// Test implementation
490
PowerMock.replayAll();
491
// Test execution
492
PowerMock.verifyAll();
493
}
494
}
495
```
496
497
## Important Notes
498
499
### Annotation Processing Order
500
501
1. PowerMock processes annotations before test method execution
502
2. Mock objects are created and made available as field values
503
3. Standard setup methods (`@Before`) run after annotation processing
504
4. Test method executes with fully configured mocks
505
506
### Integration with Dependency Injection
507
508
Annotations work well with dependency injection frameworks:
509
510
```java
511
@PowerMockListener(AnnotationEnabler.class)
512
public class DIIntegrationTest {
513
514
@Mock private DatabaseService databaseService;
515
@Mock private EmailService emailService;
516
517
@TestSubject // Automatically injects mocks into this object
518
private UserRegistrationService registrationService;
519
520
@Test
521
public void testWithDependencyInjection() {
522
// Mocks are automatically injected into registrationService
523
expect(databaseService.saveUser(anyObject(User.class))).andReturn(true);
524
expect(emailService.sendWelcomeEmail(anyString())).andReturn(true);
525
526
PowerMock.replayAll();
527
528
boolean result = registrationService.registerUser("john@example.com", "password");
529
530
assertTrue(result);
531
PowerMock.verifyAll();
532
}
533
}
534
```