0
# JUnit 5 Extensions
1
2
Modern JUnit 5 integration providing declarative test setup through annotations and extensions. Supports full application testing, resource testing, DAO testing, and lightweight client testing with automatic lifecycle management.
3
4
## Capabilities
5
6
### DropwizardAppExtension
7
8
JUnit 5 extension for complete Dropwizard application testing with automatic lifecycle management, HTTP client setup, and access to all application components.
9
10
```java { .api }
11
/**
12
* JUnit 5 extension for full Dropwizard application testing
13
* @param <C> Configuration type extending Configuration
14
*/
15
public class DropwizardAppExtension<C extends Configuration>
16
implements DropwizardExtension, BeforeAllCallback, AfterAllCallback {
17
18
// Constructor variants matching DropwizardTestSupport
19
/**
20
* Create extension with application class and configuration file
21
* @param applicationClass Dropwizard application class
22
* @param configPath Path to configuration file
23
* @param configOverrides Configuration overrides for testing
24
*/
25
public DropwizardAppExtension(Class<? extends Application<C>> applicationClass,
26
String configPath,
27
ConfigOverride... configOverrides);
28
29
/**
30
* Create extension with application class and configuration object
31
* @param applicationClass Dropwizard application class
32
* @param configuration Pre-built configuration instance
33
* @param configOverrides Configuration overrides for testing
34
*/
35
public DropwizardAppExtension(Class<? extends Application<C>> applicationClass,
36
C configuration,
37
ConfigOverride... configOverrides);
38
39
// Application access methods
40
/**
41
* Get the application configuration instance
42
* @return Configuration object used by the application
43
*/
44
public C getConfiguration();
45
46
/**
47
* Get the running Dropwizard application instance
48
* @return Application instance with full type information
49
*/
50
public <A extends Application<C>> A getApplication();
51
52
/**
53
* Get the Dropwizard runtime environment
54
* @return Environment instance with access to metrics, validation, etc.
55
*/
56
public Environment getEnvironment();
57
58
/**
59
* Get the Jackson ObjectMapper used by the application
60
* @return ObjectMapper for JSON/YAML processing
61
*/
62
public ObjectMapper getObjectMapper();
63
64
// Network access methods
65
/**
66
* Get the main application HTTP port
67
* @return Port number for application endpoints
68
*/
69
public int getLocalPort();
70
71
/**
72
* Get the admin interface HTTP port
73
* @return Port number for admin endpoints
74
*/
75
public int getAdminPort();
76
77
/**
78
* Get the port for a specific connector by index
79
* @param connectorIndex Zero-based connector index
80
* @return Port number for the specified connector
81
*/
82
public int getPort(int connectorIndex);
83
84
// HTTP testing support
85
/**
86
* Get a configured HTTP client for testing application endpoints
87
* Uses default timeouts and response buffering for reliable testing
88
* @return JAX-RS Client configured for testing
89
*/
90
public Client client();
91
92
/**
93
* Get the underlying DropwizardTestSupport instance
94
* @return DropwizardTestSupport managing the application lifecycle
95
*/
96
public DropwizardTestSupport<C> getTestSupport();
97
98
// Configuration and extension methods
99
/**
100
* Add a lifecycle listener for application events
101
* @param listener ServiceListener instance for handling events
102
* @return This DropwizardAppExtension instance for chaining
103
*/
104
public DropwizardAppExtension<C> addListener(ServiceListener<C> listener);
105
106
/**
107
* Add a managed object to the application lifecycle
108
* @param managed Managed object to start/stop with application
109
* @return This DropwizardAppExtension instance for chaining
110
*/
111
public DropwizardAppExtension<C> manage(Managed managed);
112
113
/**
114
* Create a customizable Jersey client builder
115
* Override this method to customize HTTP client configuration
116
* @return JerseyClientBuilder for custom client setup
117
*/
118
protected JerseyClientBuilder clientBuilder();
119
}
120
```
121
122
**Usage Examples:**
123
124
```java
125
// Basic application testing
126
@RegisterExtension
127
public static final DropwizardAppExtension<MyConfiguration> APP =
128
new DropwizardAppExtension<>(
129
MyApplication.class,
130
ResourceHelpers.resourceFilePath("test-config.yml")
131
);
132
133
@Test
134
public void testApplicationEndpoint() {
135
String response = APP.client()
136
.target("http://localhost:" + APP.getLocalPort() + "/api/health")
137
.request()
138
.get(String.class);
139
140
assertThat(response).contains("healthy");
141
}
142
143
// With configuration overrides
144
@RegisterExtension
145
public static final DropwizardAppExtension<MyConfiguration> APP =
146
new DropwizardAppExtension<>(
147
MyApplication.class,
148
ResourceHelpers.resourceFilePath("test-config.yml"),
149
ConfigOverride.randomPorts(),
150
ConfigOverride.config("database.url", "jdbc:h2:mem:test")
151
);
152
153
// With pre-built configuration
154
public static MyConfiguration createTestConfiguration() {
155
MyConfiguration config = new MyConfiguration();
156
config.setDatabaseUrl("jdbc:h2:mem:test");
157
config.getServerFactory().setApplicationConnectors(/* custom connectors */);
158
return config;
159
}
160
161
@RegisterExtension
162
public static final DropwizardAppExtension<MyConfiguration> APP =
163
new DropwizardAppExtension<>(MyApplication.class, createTestConfiguration());
164
165
// With lifecycle listeners
166
@RegisterExtension
167
public static final DropwizardAppExtension<MyConfiguration> APP =
168
new DropwizardAppExtension<MyConfiguration>(
169
MyApplication.class,
170
ResourceHelpers.resourceFilePath("test-config.yml")
171
).addListener(new ServiceListener<MyConfiguration>() {
172
@Override
173
public void onRun(MyConfiguration configuration,
174
Environment environment,
175
DropwizardTestSupport<MyConfiguration> rule) {
176
// Initialize test data, mock external services, etc.
177
TestDataLoader.loadTestData(environment.getApplicationContext());
178
}
179
});
180
181
// Testing with custom HTTP client configuration
182
public class CustomAppExtension extends DropwizardAppExtension<MyConfiguration> {
183
public CustomAppExtension() {
184
super(MyApplication.class, ResourceHelpers.resourceFilePath("test-config.yml"));
185
}
186
187
@Override
188
protected JerseyClientBuilder clientBuilder() {
189
return super.clientBuilder()
190
.connectTimeout(Duration.ofSeconds(10))
191
.readTimeout(Duration.ofSeconds(30))
192
.register(new CustomClientFilter());
193
}
194
}
195
196
@RegisterExtension
197
public static final CustomAppExtension APP = new CustomAppExtension();
198
```
199
200
### ResourceExtension
201
202
JUnit 5 extension for isolated JAX-RS resource testing without full application bootstrap, providing fast unit testing of individual REST endpoints.
203
204
```java { .api }
205
/**
206
* JUnit 5 extension for isolated JAX-RS resource testing
207
*/
208
public class ResourceExtension implements DropwizardExtension {
209
210
/**
211
* Create a new ResourceExtension builder for configuration
212
* @return Builder instance for fluent configuration
213
*/
214
public static Builder builder();
215
216
/**
217
* Get a JAX-RS WebTarget for making HTTP requests to resources
218
* @param path Path to append to base URI
219
* @return WebTarget for the specified path
220
*/
221
public WebTarget target(String path);
222
223
/**
224
* Get the underlying JAX-RS Client for advanced HTTP operations
225
* @return JAX-RS Client instance
226
*/
227
public Client client();
228
229
/**
230
* Get the underlying JerseyTest instance for advanced testing
231
* @return JerseyTest instance managing the test environment
232
*/
233
public JerseyTest getJerseyTest();
234
235
/**
236
* Get the Bean Validator used by the resource testing environment
237
* @return Validator instance for bean validation
238
*/
239
public Validator getValidator();
240
241
/**
242
* Get the Jackson ObjectMapper used for JSON serialization/deserialization
243
* @return ObjectMapper instance
244
*/
245
public ObjectMapper getObjectMapper();
246
247
/**
248
* Get the client configurator for custom client setup
249
* @return Consumer for ClientConfig customization
250
*/
251
public Consumer<ClientConfig> getClientConfigurator();
252
}
253
```
254
255
**Usage Examples:**
256
257
```java
258
// Basic resource testing
259
@RegisterExtension
260
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
261
.addResource(new UserResource())
262
.build();
263
264
@Test
265
public void testGetUsers() {
266
List<User> users = RESOURCE.target("/users")
267
.request(MediaType.APPLICATION_JSON)
268
.get(new GenericType<List<User>>() {});
269
270
assertThat(users).isNotEmpty();
271
}
272
273
// With dependency injection
274
UserService userService = mock(UserService.class);
275
276
@RegisterExtension
277
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
278
.addResource(new UserResource(userService))
279
.build();
280
281
@Test
282
public void testCreateUser() {
283
when(userService.create(any(User.class)))
284
.thenReturn(new User(1L, "John", "john@example.com"));
285
286
User newUser = new User("John", "john@example.com");
287
288
Response response = RESOURCE.target("/users")
289
.request()
290
.post(Entity.json(newUser));
291
292
assertThat(response.getStatus()).isEqualTo(201);
293
294
User createdUser = response.readEntity(User.class);
295
assertThat(createdUser.getId()).isNotNull();
296
}
297
```
298
299
### DAOTestExtension
300
301
JUnit 5 extension for Hibernate DAO testing with automated database setup, transaction management, and cleanup.
302
303
```java { .api }
304
/**
305
* JUnit 5 extension for Hibernate DAO testing
306
*/
307
public class DAOTestExtension implements DropwizardExtension, BeforeAllCallback, AfterAllCallback {
308
309
/**
310
* Create a new DAOTestExtension builder for configuration
311
* @return Builder instance for fluent database configuration
312
*/
313
public static Builder newBuilder();
314
315
/**
316
* Get the Hibernate SessionFactory for database operations
317
* @return SessionFactory instance for creating sessions
318
*/
319
public SessionFactory getSessionFactory();
320
321
/**
322
* Execute code within a database transaction with return value
323
* @param call Callable to execute within transaction
324
* @return Result of the callable execution
325
* @throws Exception if the callable execution fails
326
*/
327
public <T> T inTransaction(Callable<T> call) throws Exception;
328
329
/**
330
* Execute code within a database transaction without return value
331
* @param action Runnable to execute within transaction
332
* @throws Exception if the action execution fails
333
*/
334
public void inTransaction(Runnable action) throws Exception;
335
}
336
```
337
338
**Usage Examples:**
339
340
```java
341
// Basic DAO testing
342
@RegisterExtension
343
public static final DAOTestExtension DAO_TEST = DAOTestExtension.newBuilder()
344
.addEntityClass(User.class)
345
.addEntityClass(Order.class)
346
.build();
347
348
@Test
349
public void testUserDAO() throws Exception {
350
UserDAO userDAO = new UserDAO(DAO_TEST.getSessionFactory());
351
352
User user = DAO_TEST.inTransaction(() -> {
353
User newUser = new User("Alice", "alice@example.com");
354
return userDAO.save(newUser);
355
});
356
357
assertThat(user.getId()).isNotNull();
358
}
359
360
// With custom database configuration
361
@RegisterExtension
362
public static final DAOTestExtension DAO_TEST = DAOTestExtension.newBuilder()
363
.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1")
364
.addEntityClass(User.class)
365
.setShowSql(true)
366
.setHbm2DdlAuto("create-drop")
367
.build();
368
```
369
370
### DropwizardClientExtension
371
372
JUnit 5 extension for lightweight HTTP client testing with minimal Dropwizard setup.
373
374
```java { .api }
375
/**
376
* JUnit 5 extension for lightweight HTTP client testing
377
*/
378
public class DropwizardClientExtension implements DropwizardExtension {
379
380
/**
381
* Create DropwizardClientExtension with JAX-RS resources
382
* @param resources JAX-RS resource instances to register
383
*/
384
public DropwizardClientExtension(Object... resources);
385
386
/**
387
* Get the base URI for HTTP requests to the test server
388
* @return Base URI including scheme, host, and port
389
*/
390
public URI baseUri();
391
392
/**
393
* Get the Jackson ObjectMapper used by the client
394
* @return ObjectMapper instance for JSON processing
395
*/
396
public ObjectMapper getObjectMapper();
397
398
/**
399
* Get the Dropwizard Environment instance
400
* @return Environment with access to metrics, validation, etc.
401
*/
402
public Environment getEnvironment();
403
}
404
```
405
406
**Usage Examples:**
407
408
```java
409
@RegisterExtension
410
public static final DropwizardClientExtension CLIENT =
411
new DropwizardClientExtension(new UserResource(), new OrderResource());
412
413
@Test
414
public void testWithCustomHttpClient() {
415
OkHttpClient httpClient = new OkHttpClient();
416
417
Request request = new Request.Builder()
418
.url(CLIENT.baseUri().resolve("/users").toString())
419
.build();
420
421
try (Response response = httpClient.newCall(request).execute()) {
422
assertThat(response.isSuccessful()).isTrue();
423
}
424
}
425
```
426
427
### DropwizardExtensionsSupport
428
429
Automatic discovery and lifecycle management extension that finds and manages all DropwizardExtension fields in test classes.
430
431
```java { .api }
432
/**
433
* Extension for automatic discovery of DropwizardExtension fields
434
* Implements JUnit 5 lifecycle callbacks for managing extensions
435
*/
436
public class DropwizardExtensionsSupport
437
implements BeforeAllCallback, BeforeEachCallback, AfterAllCallback, AfterEachCallback {
438
439
// Automatically discovers and manages DropwizardExtension fields
440
// No public API - register as extension to enable automatic field discovery
441
}
442
```
443
444
**Usage Examples:**
445
446
```java
447
@ExtendWith(DropwizardExtensionsSupport.class)
448
public class AutoDiscoveryTest {
449
450
// Extensions are automatically discovered and managed
451
public final DropwizardAppExtension<MyConfiguration> app =
452
new DropwizardAppExtension<>(MyApplication.class, "test-config.yml");
453
454
public final ResourceExtension resource = ResourceExtension.builder()
455
.addResource(new UserResource())
456
.build();
457
458
@Test
459
public void testWithAutoDiscovery() {
460
// Extensions are automatically started before this test
461
String response = app.client()
462
.target("http://localhost:" + app.getLocalPort() + "/api/users")
463
.request()
464
.get(String.class);
465
466
assertThat(response).isNotNull();
467
}
468
}
469
```
470
471
## Common Extension Patterns
472
473
### Parameterized Testing
474
475
```java
476
@RegisterExtension
477
public static final DropwizardAppExtension<MyConfiguration> APP =
478
new DropwizardAppExtension<>(MyApplication.class, "test-config.yml");
479
480
@ParameterizedTest
481
@ValueSource(strings = {"/api/users", "/api/orders", "/api/products"})
482
public void testEndpoints(String endpoint) {
483
Response response = APP.client()
484
.target("http://localhost:" + APP.getLocalPort() + endpoint)
485
.request()
486
.get();
487
488
assertThat(response.getStatus()).isEqualTo(200);
489
}
490
```
491
492
### Nested Test Classes
493
494
```java
495
@RegisterExtension
496
public static final DropwizardAppExtension<MyConfiguration> APP =
497
new DropwizardAppExtension<>(MyApplication.class, "test-config.yml");
498
499
@Nested
500
@DisplayName("User API Tests")
501
class UserApiTests {
502
503
@Test
504
public void testGetUsers() {
505
// Test user retrieval
506
}
507
508
@Test
509
public void testCreateUser() {
510
// Test user creation
511
}
512
}
513
514
@Nested
515
@DisplayName("Order API Tests")
516
class OrderApiTests {
517
518
@Test
519
public void testGetOrders() {
520
// Test order retrieval
521
}
522
}
523
```
524
525
### Test Instance Lifecycle
526
527
```java
528
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
529
public class InstancePerClassTest {
530
531
// Extension can be non-static with PER_CLASS lifecycle
532
@RegisterExtension
533
public final DropwizardAppExtension<MyConfiguration> app =
534
new DropwizardAppExtension<>(MyApplication.class, "test-config.yml");
535
536
private TestDataService testDataService;
537
538
@BeforeAll
539
public void setUp() {
540
// Initialize test data service after application starts
541
testDataService = new TestDataService(app.getEnvironment());
542
testDataService.loadTestData();
543
}
544
545
@Test
546
public void testWithPreloadedData() {
547
// Test with data loaded in @BeforeAll
548
}
549
}
550
```
551
552
### Custom Extension Configuration
553
554
```java
555
public class CustomTestExtension extends DropwizardAppExtension<MyConfiguration> {
556
557
public CustomTestExtension() {
558
super(MyApplication.class, createCustomConfig());
559
}
560
561
private static MyConfiguration createCustomConfig() {
562
MyConfiguration config = new MyConfiguration();
563
config.setDatabaseUrl("jdbc:h2:mem:custom_test");
564
config.setLogLevel("DEBUG");
565
return config;
566
}
567
568
@Override
569
protected JerseyClientBuilder clientBuilder() {
570
return super.clientBuilder()
571
.connectTimeout(Duration.ofSeconds(30))
572
.readTimeout(Duration.ofMinutes(2))
573
.register(new RequestLoggingFilter())
574
.register(new ResponseLoggingFilter());
575
}
576
}
577
578
@RegisterExtension
579
public static final CustomTestExtension APP = new CustomTestExtension();
580
```