0
# Test Resource Management
1
2
Comprehensive lifecycle management for external test dependencies like databases, message brokers, and external services. The test resource system provides sophisticated scoping strategies, parallel resource startup, and automatic configuration injection.
3
4
## Capabilities
5
6
### QuarkusTestResource Annotation
7
8
Defines test resources for lifecycle management with optional configuration and scoping control.
9
10
```java { .api }
11
@Target(ElementType.TYPE)
12
@Retention(RetentionPolicy.RUNTIME)
13
@Repeatable(QuarkusTestResource.List.class)
14
public @interface QuarkusTestResource {
15
Class<? extends QuarkusTestResourceLifecycleManager> value();
16
ResourceArg[] initArgs() default {};
17
boolean parallel() default false;
18
boolean restrictToAnnotatedClass() default false;
19
}
20
21
@Target(ElementType.TYPE)
22
@Retention(RetentionPolicy.RUNTIME)
23
public @interface ResourceArg {
24
String name();
25
String value();
26
}
27
```
28
29
**Usage Example:**
30
```java
31
@QuarkusTestResource(value = DatabaseTestResource.class,
32
initArgs = @ResourceArg(name = "db.version", value = "13"))
33
public class UserServiceTest {
34
// Test implementation
35
}
36
```
37
38
### WithTestResource Annotation
39
40
Alternative to QuarkusTestResource with enhanced scope control for resource sharing and isolation.
41
42
```java { .api }
43
@Target(ElementType.TYPE)
44
@Retention(RetentionPolicy.RUNTIME)
45
@Repeatable(WithTestResource.List.class)
46
public @interface WithTestResource {
47
Class<? extends QuarkusTestResourceLifecycleManager> value();
48
ResourceArg[] initArgs() default {};
49
boolean parallel() default false;
50
TestResourceScope scope() default TestResourceScope.MATCHING_RESOURCES;
51
}
52
53
public enum TestResourceScope {
54
RESTRICTED_TO_CLASS, // Complete isolation, restart for each test
55
MATCHING_RESOURCES, // Restart only when resources differ
56
GLOBAL // Apply to all tests in suite
57
}
58
```
59
60
**Usage Example:**
61
```java
62
@WithTestResource(value = DatabaseTestResource.class,
63
scope = TestResourceScope.GLOBAL)
64
public class IntegrationTest {
65
// Shared database resource across all tests
66
}
67
```
68
69
### QuarkusTestResourceLifecycleManager Interface
70
71
Main interface for managing test resource lifecycle with hooks for initialization, injection, and cleanup.
72
73
```java { .api }
74
public interface QuarkusTestResourceLifecycleManager {
75
Map<String, String> start();
76
void stop();
77
default void setContext(Context context) {}
78
default void init(Map<String, String> initArgs) {}
79
default void inject(Object testInstance) {}
80
default void inject(TestInjector testInjector) {}
81
default int order() { return 0; }
82
83
interface Context {
84
String testProfile();
85
TestStatus getTestStatus();
86
}
87
88
interface TestInjector {
89
void injectIntoFields(Object fieldValue, Predicate<Field> predicate);
90
91
class Annotated implements Predicate<Field> {
92
public Annotated(Class<? extends Annotation> annotationType) {}
93
}
94
95
class MatchesType implements Predicate<Field> {
96
public MatchesType(Class<?> type) {}
97
}
98
99
class AnnotatedAndMatchesType implements Predicate<Field> {
100
public AnnotatedAndMatchesType(Class<? extends Annotation> annotationType, Class<?> type) {}
101
}
102
}
103
}
104
```
105
106
**Implementation Example:**
107
```java
108
public class DatabaseTestResource implements QuarkusTestResourceLifecycleManager {
109
private PostgreSQLContainer<?> container;
110
111
@Override
112
public Map<String, String> start() {
113
container = new PostgreSQLContainer<>("postgres:13")
114
.withDatabaseName("testdb")
115
.withUsername("test")
116
.withPassword("test");
117
container.start();
118
119
return Map.of(
120
"quarkus.datasource.jdbc.url", container.getJdbcUrl(),
121
"quarkus.datasource.username", container.getUsername(),
122
"quarkus.datasource.password", container.getPassword()
123
);
124
}
125
126
@Override
127
public void stop() {
128
if (container != null) {
129
container.stop();
130
}
131
}
132
133
@Override
134
public void inject(TestInjector testInjector) {
135
testInjector.injectIntoFields(container,
136
new TestInjector.MatchesType(PostgreSQLContainer.class));
137
}
138
139
@Override
140
public int order() {
141
return 100; // Start after other resources
142
}
143
}
144
```
145
146
### QuarkusTestResourceConfigurableLifecycleManager Interface
147
148
Lifecycle manager with annotation-based configuration for type-safe resource initialization.
149
150
```java { .api }
151
public interface QuarkusTestResourceConfigurableLifecycleManager<ConfigAnnotation extends Annotation>
152
extends QuarkusTestResourceLifecycleManager {
153
default void init(ConfigAnnotation annotation) {}
154
}
155
```
156
157
**Usage Example:**
158
```java
159
@Target(ElementType.TYPE)
160
@Retention(RetentionPolicy.RUNTIME)
161
public @interface DatabaseConfig {
162
String version() default "13";
163
boolean withData() default false;
164
}
165
166
public class ConfigurableDatabaseResource
167
implements QuarkusTestResourceConfigurableLifecycleManager<DatabaseConfig> {
168
169
private DatabaseConfig config;
170
171
@Override
172
public void init(DatabaseConfig annotation) {
173
this.config = annotation;
174
}
175
176
@Override
177
public Map<String, String> start() {
178
// Use config.version() and config.withData() for setup
179
return configMap;
180
}
181
}
182
```
183
184
## Advanced Usage Patterns
185
186
### Resource Ordering
187
188
Control resource startup order using the `order()` method:
189
190
```java
191
public class DatabaseResource implements QuarkusTestResourceLifecycleManager {
192
@Override
193
public int order() { return 10; } // Start early
194
}
195
196
public class CacheResource implements QuarkusTestResourceLifecycleManager {
197
@Override
198
public int order() { return 20; } // Start after database
199
}
200
```
201
202
### Resource Context Access
203
204
Access test execution context and failure status:
205
206
```java
207
public class MonitoringResource implements QuarkusTestResourceLifecycleManager {
208
private Context context;
209
210
@Override
211
public void setContext(Context context) {
212
this.context = context;
213
}
214
215
@Override
216
public void stop() {
217
if (context.getTestStatus().isTestFailed()) {
218
// Capture logs for failed tests
219
captureLogs();
220
}
221
}
222
}
223
```
224
225
### Custom Field Injection
226
227
Inject resource instances directly into test fields:
228
229
```java
230
public class MyTestResource implements QuarkusTestResourceLifecycleManager {
231
private CustomService service;
232
233
@Override
234
public Map<String, String> start() {
235
service = new CustomService();
236
return Map.of();
237
}
238
239
@Override
240
public void inject(TestInjector testInjector) {
241
testInjector.injectIntoFields(service,
242
new TestInjector.Annotated(CustomService.class));
243
}
244
}
245
246
// In test class:
247
public class MyTest {
248
@CustomService
249
CustomService injectedService; // Automatically injected
250
}
251
```
252
253
### Parallel Resource Startup
254
255
Enable parallel startup for independent resources:
256
257
```java
258
@QuarkusTestResource(value = DatabaseResource.class, parallel = true)
259
@QuarkusTestResource(value = MessageBrokerResource.class, parallel = true)
260
public class IntegrationTest {
261
// Both resources start in parallel
262
}
263
```