0
# Resource Testing
1
2
Lightweight JAX-RS resource testing utilities providing isolated testing environment without full Dropwizard application bootstrap. Perfect for unit testing individual REST endpoints with minimal overhead and fast execution.
3
4
## Capabilities
5
6
### Resource
7
8
Core utility class for creating isolated JAX-RS resource testing environments with configurable Jackson ObjectMapper, Bean Validation, and Jersey providers.
9
10
```java { .api }
11
/**
12
* Utility class for isolated JAX-RS resource testing
13
*/
14
public class Resource {
15
16
/**
17
* Create a new Resource builder for configuration
18
* @return Builder instance for fluent configuration
19
*/
20
public static Builder builder();
21
22
/**
23
* Get a JAX-RS WebTarget for making HTTP requests to resources
24
* @param path Path to append to base URI
25
* @return WebTarget for the specified path
26
*/
27
public WebTarget target(String path);
28
29
/**
30
* Get the underlying JAX-RS Client for advanced HTTP operations
31
* @return JAX-RS Client instance
32
*/
33
public Client client();
34
35
/**
36
* Get the underlying JerseyTest instance for advanced testing
37
* @return JerseyTest instance managing the test environment
38
*/
39
public JerseyTest getJerseyTest();
40
41
/**
42
* Get the Bean Validator used by the resource testing environment
43
* @return Validator instance for bean validation
44
*/
45
public Validator getValidator();
46
47
/**
48
* Get the Jackson ObjectMapper used for JSON serialization/deserialization
49
* @return ObjectMapper instance
50
*/
51
public ObjectMapper getObjectMapper();
52
53
/**
54
* Get the client configurator for custom client setup
55
* @return Consumer for ClientConfig customization
56
*/
57
public Consumer<ClientConfig> getClientConfigurator();
58
59
// Lifecycle methods
60
/**
61
* Initialize the resource testing environment before tests
62
* @throws Exception if initialization fails
63
*/
64
public void before() throws Exception;
65
66
/**
67
* Cleanup the resource testing environment after tests
68
* @throws Exception if cleanup fails
69
*/
70
public void after() throws Exception;
71
}
72
```
73
74
### Resource.Builder
75
76
Fluent builder for configuring Resource testing environments with custom ObjectMapper, validators, providers, and Jersey settings.
77
78
```java { .api }
79
/**
80
* Fluent builder for Resource configuration
81
*/
82
public static class Builder<B extends Builder<B>> {
83
84
// Resource configuration
85
/**
86
* Add a JAX-RS resource instance to the testing environment
87
* @param resource Resource instance to add
88
* @return Builder instance for chaining
89
*/
90
public B addResource(Object resource);
91
92
/**
93
* Add a JAX-RS resource using a supplier for lazy initialization
94
* @param resourceSupplier Supplier providing the resource instance
95
* @return Builder instance for chaining
96
*/
97
public B addResource(Supplier<Object> resourceSupplier);
98
99
// Provider configuration
100
/**
101
* Add a JAX-RS provider class to the testing environment
102
* @param klass Provider class to register
103
* @return Builder instance for chaining
104
*/
105
public B addProvider(Class<?> klass);
106
107
/**
108
* Add a JAX-RS provider instance to the testing environment
109
* @param provider Provider instance to register
110
* @return Builder instance for chaining
111
*/
112
public B addProvider(Object provider);
113
114
// Component customization
115
/**
116
* Set a custom Jackson ObjectMapper for JSON processing
117
* @param mapper Custom ObjectMapper instance
118
* @return Builder instance for chaining
119
*/
120
public B setMapper(ObjectMapper mapper);
121
122
/**
123
* Set a custom MetricRegistry for metrics collection
124
* @param metricRegistry Custom MetricRegistry instance
125
* @return Builder instance for chaining
126
*/
127
public B setMetricRegistry(MetricRegistry metricRegistry);
128
129
/**
130
* Set a custom Bean Validator for request/response validation
131
* @param validator Custom Validator instance
132
* @return Builder instance for chaining
133
*/
134
public B setValidator(Validator validator);
135
136
// Jersey configuration
137
/**
138
* Set a custom client configurator for HTTP client setup
139
* @param clientConfigurator Consumer for ClientConfig customization
140
* @return Builder instance for chaining
141
*/
142
public B setClientConfigurator(Consumer<ClientConfig> clientConfigurator);
143
144
/**
145
* Add a Jersey property to the testing environment
146
* @param property Property name
147
* @param value Property value
148
* @return Builder instance for chaining
149
*/
150
public B addProperty(String property, Object value);
151
152
/**
153
* Set a custom TestContainerFactory for Jersey testing
154
* @param factory Custom TestContainerFactory instance
155
* @return Builder instance for chaining
156
*/
157
public B setTestContainerFactory(TestContainerFactory factory);
158
159
/**
160
* Configure whether to register default exception mappers
161
* @param value true to register default exception mappers, false otherwise
162
* @return Builder instance for chaining
163
*/
164
public B setRegisterDefaultExceptionMappers(boolean value);
165
166
/**
167
* Configure whether to bootstrap Logback logging
168
* @param value true to bootstrap logging, false otherwise
169
* @return Builder instance for chaining
170
*/
171
public B bootstrapLogging(boolean value);
172
173
/**
174
* Build the configured Resource instance
175
* @return Configured Resource instance ready for testing
176
*/
177
public Resource build();
178
}
179
```
180
181
**Usage Examples:**
182
183
```java
184
// Basic resource testing
185
@RegisterExtension
186
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
187
.addResource(new UserResource())
188
.build();
189
190
@Test
191
public void testGetUser() {
192
User user = RESOURCE.target("/users/123")
193
.request(MediaType.APPLICATION_JSON)
194
.get(User.class);
195
196
assertThat(user.getId()).isEqualTo(123);
197
}
198
199
// With custom ObjectMapper and providers
200
@RegisterExtension
201
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
202
.addResource(new UserResource())
203
.addProvider(new CustomExceptionMapper())
204
.addProvider(new ValidationFeature())
205
.setMapper(createCustomObjectMapper())
206
.build();
207
208
// With multiple resources and shared dependencies
209
UserService userService = mock(UserService.class);
210
EmailService emailService = mock(EmailService.class);
211
212
@RegisterExtension
213
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
214
.addResource(new UserResource(userService))
215
.addResource(new EmailResource(emailService))
216
.addProvider(new AuthenticationFilter())
217
.setValidator(Validation.buildDefaultValidatorFactory().getValidator())
218
.build();
219
220
// Advanced configuration with custom client setup
221
@RegisterExtension
222
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
223
.addResource(new ApiResource())
224
.setClientConfigurator(clientConfig -> {
225
clientConfig.register(new LoggingFeature());
226
clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 5000);
227
clientConfig.property(ClientProperties.READ_TIMEOUT, 10000);
228
})
229
.addProperty(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true)
230
.build();
231
232
@Test
233
public void testResourceValidation() {
234
Response response = RESOURCE.target("/api/users")
235
.request()
236
.post(Entity.json("{ \"invalid\": \"data\" }"));
237
238
assertThat(response.getStatus()).isEqualTo(400);
239
240
ValidationErrorResponse error = response.readEntity(ValidationErrorResponse.class);
241
assertThat(error.getErrors()).isNotEmpty();
242
}
243
244
// Testing with different content types
245
@Test
246
public void testContentNegotiation() {
247
// JSON request/response
248
User jsonUser = RESOURCE.target("/users/123")
249
.request(MediaType.APPLICATION_JSON)
250
.get(User.class);
251
252
// XML request/response
253
User xmlUser = RESOURCE.target("/users/123")
254
.request(MediaType.APPLICATION_XML)
255
.get(User.class);
256
257
assertThat(jsonUser).isEqualTo(xmlUser);
258
}
259
260
// Testing error handling
261
@Test
262
public void testErrorHandling() {
263
Response response = RESOURCE.target("/users/999")
264
.request()
265
.get();
266
267
assertThat(response.getStatus()).isEqualTo(404);
268
269
ErrorResponse error = response.readEntity(ErrorResponse.class);
270
assertThat(error.getMessage()).contains("User not found");
271
}
272
```
273
274
### DropwizardClient
275
276
Lightweight HTTP client testing utility providing minimal Dropwizard setup for testing HTTP interactions without full application bootstrap.
277
278
```java { .api }
279
/**
280
* Lightweight HTTP client for testing REST endpoints
281
*/
282
public class DropwizardClient {
283
284
/**
285
* Create DropwizardClient with JAX-RS resources
286
* @param resources JAX-RS resource instances to register
287
*/
288
public DropwizardClient(Object... resources);
289
290
/**
291
* Get the base URI for HTTP requests to the test server
292
* @return Base URI including scheme, host, and port
293
*/
294
public URI baseUri();
295
296
/**
297
* Get the Jackson ObjectMapper used by the client
298
* @return ObjectMapper instance for JSON processing
299
*/
300
public ObjectMapper getObjectMapper();
301
302
/**
303
* Get the Dropwizard Environment instance
304
* @return Environment with access to metrics, validation, etc.
305
*/
306
public Environment getEnvironment();
307
308
// Lifecycle methods
309
/**
310
* Initialize the client testing environment before tests
311
* @throws Exception if initialization fails
312
*/
313
public void before() throws Exception;
314
315
/**
316
* Cleanup the client testing environment after tests
317
* @throws Exception if cleanup fails
318
*/
319
public void after() throws Exception;
320
}
321
```
322
323
**Usage Examples:**
324
325
```java
326
// Manual client setup
327
DropwizardClient client = new DropwizardClient(
328
new UserResource(),
329
new OrderResource()
330
);
331
332
@BeforeEach
333
public void setUp() throws Exception {
334
client.before();
335
}
336
337
@AfterEach
338
public void tearDown() throws Exception {
339
client.after();
340
}
341
342
@Test
343
public void testWithHttpClient() {
344
URI baseUri = client.baseUri();
345
346
// Use any HTTP client library
347
String response = HttpClient.newHttpClient()
348
.send(HttpRequest.newBuilder()
349
.uri(baseUri.resolve("/users"))
350
.build(),
351
HttpResponse.BodyHandlers.ofString())
352
.body();
353
354
assertThat(response).contains("users");
355
}
356
357
// With OkHttp client
358
@Test
359
public void testWithOkHttp() {
360
OkHttpClient httpClient = new OkHttpClient();
361
Request request = new Request.Builder()
362
.url(client.baseUri().resolve("/users").toString())
363
.build();
364
365
try (okhttp3.Response response = httpClient.newCall(request).execute()) {
366
assertThat(response.isSuccessful()).isTrue();
367
String body = response.body().string();
368
assertThat(body).isNotNull();
369
}
370
}
371
```
372
373
## Common Testing Patterns
374
375
### Resource Validation Testing
376
377
```java
378
@RegisterExtension
379
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
380
.addResource(new UserResource())
381
.setRegisterDefaultExceptionMappers(true)
382
.build();
383
384
@Test
385
public void testValidationErrors() {
386
// Invalid user data
387
User invalidUser = new User();
388
invalidUser.setEmail("invalid-email");
389
390
Response response = RESOURCE.target("/users")
391
.request()
392
.post(Entity.json(invalidUser));
393
394
assertThat(response.getStatus()).isEqualTo(422);
395
396
ValidationErrorMessage error = response.readEntity(ValidationErrorMessage.class);
397
assertThat(error.getErrors()).containsKey("email");
398
}
399
```
400
401
### Exception Mapper Testing
402
403
```java
404
@RegisterExtension
405
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
406
.addResource(new UserResource())
407
.addProvider(new CustomExceptionMapper())
408
.build();
409
410
@Test
411
public void testCustomExceptionHandling() {
412
Response response = RESOURCE.target("/users/trigger-custom-exception")
413
.request()
414
.get();
415
416
assertThat(response.getStatus()).isEqualTo(418);
417
assertThat(response.getHeaderString("X-Custom-Error")).isEqualTo("true");
418
}
419
```
420
421
### Authentication Filter Testing
422
423
```java
424
@RegisterExtension
425
public static final ResourceExtension RESOURCE = ResourceExtension.builder()
426
.addResource(new SecureResource())
427
.addProvider(new AuthenticationFilter())
428
.build();
429
430
@Test
431
public void testAuthenticationRequired() {
432
Response response = RESOURCE.target("/secure/data")
433
.request()
434
.get();
435
436
assertThat(response.getStatus()).isEqualTo(401);
437
}
438
439
@Test
440
public void testAuthenticatedAccess() {
441
Response response = RESOURCE.target("/secure/data")
442
.request()
443
.header("Authorization", "Bearer valid-token")
444
.get();
445
446
assertThat(response.getStatus()).isEqualTo(200);
447
}
448
```