0
# Conditional Testing
1
2
Quarkus JUnit 5 provides annotations for conditionally enabling or disabling tests based on various criteria including integration test mode, GraalVM versions, and artifact types.
3
4
## Integration Test Conditional Execution
5
6
### @DisabledOnIntegrationTest
7
8
Disables tests when running as `@QuarkusIntegrationTest`, useful for tests that require CDI injection or only make sense in unit test context.
9
10
```java { .api }
11
@Target({ElementType.TYPE, ElementType.METHOD})
12
@Retention(RetentionPolicy.RUNTIME)
13
@Documented
14
@Inherited
15
public @interface DisabledOnIntegrationTest {
16
/**
17
* Reason for disabling this test
18
*/
19
String value() default "";
20
21
/**
22
* The types of Quarkus application produced by the build for which this test is disabled.
23
*/
24
ArtifactType[] forArtifactTypes() default {ArtifactType.ALL};
25
26
enum ArtifactType {
27
ALL, JAR, CONTAINER, NATIVE_BINARY
28
}
29
}
30
```
31
32
### Usage Examples
33
34
#### Class-Level Disabling
35
36
```java
37
import io.quarkus.test.junit.QuarkusTest;
38
import io.quarkus.test.junit.QuarkusIntegrationTest;
39
import io.quarkus.test.junit.DisabledOnIntegrationTest;
40
import jakarta.inject.Inject;
41
42
@QuarkusTest
43
@DisabledOnIntegrationTest("CDI injection not available in integration tests")
44
class UnitTestOnlyTest {
45
46
@Inject
47
UserService userService; // Only works in @QuarkusTest
48
49
@Test
50
void testCdiInjection() {
51
assertNotNull(userService);
52
User user = userService.createUser("test@example.com");
53
assertNotNull(user.getId());
54
}
55
}
56
57
// Integration test without CDI-dependent tests
58
@QuarkusIntegrationTest
59
class UserServiceIT extends UnitTestOnlyTest {
60
// Inherits tests but @DisabledOnIntegrationTest tests are skipped
61
62
@Test
63
void testHttpEndpoint() {
64
given()
65
.when().get("/api/users")
66
.then()
67
.statusCode(200);
68
}
69
}
70
```
71
72
#### Method-Level Disabling
73
74
```java
75
@QuarkusTest
76
class MixedTestModes {
77
78
@Test
79
@DisabledOnIntegrationTest("Requires direct database access")
80
void testDatabaseDirectly() {
81
// Test that directly accesses database - not available in integration tests
82
}
83
84
@Test
85
void testHttpApi() {
86
// Test that works in both unit and integration tests
87
given()
88
.when().get("/api/health")
89
.then()
90
.statusCode(200);
91
}
92
}
93
```
94
95
#### Artifact-Specific Disabling
96
97
```java
98
@QuarkusTest
99
class ArtifactSpecificTest {
100
101
@Test
102
@DisabledOnIntegrationTest(
103
value = "Container has different network setup",
104
forArtifactTypes = {DisabledOnIntegrationTest.ArtifactType.CONTAINER}
105
)
106
void testNetworkConfiguration() {
107
// Disabled only when running against container, enabled for JAR and native
108
}
109
110
@Test
111
@DisabledOnIntegrationTest(
112
value = "Native image specific test",
113
forArtifactTypes = {
114
DisabledOnIntegrationTest.ArtifactType.JAR,
115
DisabledOnIntegrationTest.ArtifactType.CONTAINER
116
}
117
)
118
void testNativeImageOptimization() {
119
// Only runs against native binary
120
}
121
}
122
```
123
124
## GraalVM Version Conditional Execution
125
126
### @DisableIfBuiltWithGraalVMNewerThan
127
128
Disables tests if the GraalVM version used to build the native image is newer than the specified version.
129
130
```java { .api }
131
@Target({ElementType.TYPE, ElementType.METHOD})
132
@Retention(RetentionPolicy.RUNTIME)
133
@ExtendWith(DisableIfBuiltWithGraalVMNewerThanCondition.class)
134
public @interface DisableIfBuiltWithGraalVMNewerThan {
135
GraalVMVersion value();
136
}
137
```
138
139
### @DisableIfBuiltWithGraalVMOlderThan
140
141
Disables tests if the GraalVM version used to build the native image is older than the specified version.
142
143
```java { .api }
144
@Target({ElementType.TYPE, ElementType.METHOD})
145
@Retention(RetentionPolicy.RUNTIME)
146
@ExtendWith(DisableIfBuiltWithGraalVMOlderThanCondition.class)
147
public @interface DisableIfBuiltWithGraalVMOlderThan {
148
GraalVMVersion value();
149
}
150
```
151
152
### GraalVMVersion Enum
153
154
```java { .api }
155
public enum GraalVMVersion {
156
GRAALVM_23_1_0(GraalVM.Version.VERSION_23_1_0),
157
GRAALVM_24_0_0(GraalVM.Version.VERSION_24_0_0),
158
GRAALVM_24_0_999(GraalVM.Version.VERSION_24_0_999),
159
GRAALVM_24_1_0(GraalVM.Version.VERSION_24_1_0),
160
GRAALVM_24_1_999(GraalVM.Version.VERSION_24_1_999),
161
GRAALVM_24_2_0(GraalVM.Version.VERSION_24_2_0);
162
163
public GraalVM.Version getVersion();
164
public String toString();
165
}
166
```
167
168
### GraalVM Version Usage Examples
169
170
#### Feature Compatibility Testing
171
172
```java
173
import io.quarkus.test.junit.QuarkusIntegrationTest;
174
import io.quarkus.test.junit.DisableIfBuiltWithGraalVMOlderThan;
175
import io.quarkus.test.junit.DisableIfBuiltWithGraalVMNewerThan;
176
import io.quarkus.test.junit.GraalVMVersion;
177
178
@QuarkusIntegrationTest
179
class GraalVMVersionTest {
180
181
@Test
182
@DisableIfBuiltWithGraalVMOlderThan(GraalVMVersion.GRAALVM_24_0_0)
183
void testNewGraalVMFeature() {
184
// Test feature that requires GraalVM 24.0.0 or newer
185
given()
186
.when().get("/api/advanced-feature")
187
.then()
188
.statusCode(200);
189
}
190
191
@Test
192
@DisableIfBuiltWithGraalVMNewerThan(GraalVMVersion.GRAALVM_24_1_999)
193
void testLegacyBehavior() {
194
// Test behavior that changed in newer GraalVM versions
195
given()
196
.when().get("/api/legacy-endpoint")
197
.then()
198
.statusCode(200)
199
.body("format", equalTo("legacy"));
200
}
201
}
202
```
203
204
#### Class-Level Version Requirements
205
206
```java
207
@QuarkusIntegrationTest
208
@DisableIfBuiltWithGraalVMOlderThan(GraalVMVersion.GRAALVM_24_1_0)
209
class ModernGraalVMTest {
210
211
@Test
212
void testModernFeatureOne() {
213
// All tests in this class require GraalVM 24.1.0+
214
}
215
216
@Test
217
void testModernFeatureTwo() {
218
// This test also requires GraalVM 24.1.0+
219
}
220
}
221
```
222
223
#### Version Range Testing
224
225
```java
226
@QuarkusIntegrationTest
227
class VersionRangeTest {
228
229
@Test
230
@DisableIfBuiltWithGraalVMOlderThan(GraalVMVersion.GRAALVM_24_0_0)
231
@DisableIfBuiltWithGraalVMNewerThan(GraalVMVersion.GRAALVM_24_1_999)
232
void testSpecificVersionRange() {
233
// Test only runs with GraalVM 24.0.0 through 24.1.999
234
given()
235
.when().get("/api/version-specific")
236
.then()
237
.statusCode(200);
238
}
239
}
240
```
241
242
## Complex Conditional Scenarios
243
244
### Combining Multiple Conditions
245
246
```java
247
@QuarkusTest
248
class ComplexConditionalTest {
249
250
@Test
251
@DisabledOnIntegrationTest("Requires CDI injection")
252
@EnabledIf("#{systemProperties['test.mode'] == 'full'}")
253
void testComplexScenario() {
254
// Only runs in unit tests AND when test.mode=full
255
}
256
257
@Test
258
@DisabledOnIntegrationTest(
259
value = "Container networking differs",
260
forArtifactTypes = {DisabledOnIntegrationTest.ArtifactType.CONTAINER}
261
)
262
@DisableIfBuiltWithGraalVMOlderThan(GraalVMVersion.GRAALVM_24_0_0)
263
void testModernNativeFeature() {
264
// Disabled on containers and old GraalVM versions
265
}
266
}
267
```
268
269
### Environment-Specific Testing
270
271
```java
272
@QuarkusIntegrationTest
273
class EnvironmentConditionalTest {
274
275
@Test
276
@DisabledOnIntegrationTest(
277
forArtifactTypes = {DisabledOnIntegrationTest.ArtifactType.NATIVE_BINARY}
278
)
279
@EnabledIf("#{environment['CI'] == null}")
280
void testLocalDevelopmentOnly() {
281
// Only runs locally, not in CI, and not against native images
282
}
283
284
@Test
285
@DisableIfBuiltWithGraalVMOlderThan(GraalVMVersion.GRAALVM_24_1_0)
286
@EnabledIf("#{systemProperties['quarkus.native.enabled'] == 'true'}")
287
void testNativeImageWithModernGraalVM() {
288
// Only runs for native builds with GraalVM 24.1.0+
289
}
290
}
291
```
292
293
## Testing Pattern Examples
294
295
### Base Test Class Pattern
296
297
```java
298
// Base test class with unit tests
299
@QuarkusTest
300
class BaseServiceTest {
301
302
@Test
303
@DisabledOnIntegrationTest("Requires CDI injection")
304
void testServiceDependencyInjection() {
305
// Unit test specific logic
306
}
307
308
@Test
309
void testServiceHttpEndpoint() {
310
// Works in both unit and integration tests
311
given()
312
.when().get("/api/service")
313
.then()
314
.statusCode(200);
315
}
316
}
317
318
// Integration test inherits base tests
319
@QuarkusIntegrationTest
320
class ServiceIntegrationTest extends BaseServiceTest {
321
// CDI-dependent tests are automatically skipped
322
323
@Test
324
@DisableIfBuiltWithGraalVMOlderThan(GraalVMVersion.GRAALVM_24_0_0)
325
void testNativeSpecificBehavior() {
326
// Integration test specific to newer GraalVM
327
}
328
}
329
```
330
331
### Platform-Specific Testing
332
333
```java
334
@QuarkusIntegrationTest
335
class PlatformSpecificTest {
336
337
@Test
338
@DisabledOnIntegrationTest(
339
value = "JVM heap analysis not available in containers",
340
forArtifactTypes = {DisabledOnIntegrationTest.ArtifactType.CONTAINER}
341
)
342
void testMemoryUsage() {
343
// Memory analysis test
344
}
345
346
@Test
347
@DisabledOnIntegrationTest(
348
forArtifactTypes = {
349
DisabledOnIntegrationTest.ArtifactType.JAR,
350
DisabledOnIntegrationTest.ArtifactType.NATIVE_BINARY
351
}
352
)
353
void testContainerSpecificFeature() {
354
// Test that only runs in container environment
355
}
356
}
357
```
358
359
### Version Migration Testing
360
361
```java
362
@QuarkusIntegrationTest
363
class MigrationTest {
364
365
@Test
366
@DisableIfBuiltWithGraalVMNewerThan(GraalVMVersion.GRAALVM_23_1_0)
367
void testLegacyCompatibility() {
368
// Test legacy behavior for older versions
369
given()
370
.when().get("/api/legacy")
371
.then()
372
.statusCode(200)
373
.body("version", equalTo("legacy"));
374
}
375
376
@Test
377
@DisableIfBuiltWithGraalVMOlderThan(GraalVMVersion.GRAALVM_24_0_0)
378
void testNewApiFeatures() {
379
// Test new features available in modern versions
380
given()
381
.when().get("/api/modern")
382
.then()
383
.statusCode(200)
384
.body("features", hasItems("new-feature-1", "new-feature-2"));
385
}
386
}
387
```
388
389
## Best Practices
390
391
### Descriptive Disable Reasons
392
393
```java
394
@Test
395
@DisabledOnIntegrationTest("Test requires @Inject UserService which is not available in integration tests")
396
void testWithGoodReason() {
397
// Clear explanation helps maintainers understand why test is disabled
398
}
399
400
@Test
401
@DisableIfBuiltWithGraalVMOlderThan(GraalVMVersion.GRAALVM_24_1_0)
402
void testRequiringNewGraalVM() {
403
// Version requirements are self-documenting
404
}
405
```
406
407
### Minimal Disabling
408
409
```java
410
@QuarkusTest
411
class MinimalDisablingTest {
412
413
@Inject
414
UserService userService;
415
416
@Test
417
void testBusinessLogic() {
418
// Test that works in both modes - no disabling needed
419
User user = userService.createUser("test@example.com");
420
assertNotNull(user);
421
}
422
423
@Test
424
@DisabledOnIntegrationTest("Requires CDI injection")
425
void testCdiSpecificBehavior() {
426
// Only disable when absolutely necessary
427
assertNotNull(userService);
428
}
429
}
430
```
431
432
### Documentation and Comments
433
434
```java
435
@QuarkusIntegrationTest
436
class WellDocumentedTest {
437
438
/**
439
* This test verifies container-specific networking behavior.
440
* It's disabled for JAR and native runs because they use
441
* different network configurations.
442
*/
443
@Test
444
@DisabledOnIntegrationTest(
445
value = "Container networking configuration differs from JAR/native",
446
forArtifactTypes = {
447
DisabledOnIntegrationTest.ArtifactType.JAR,
448
DisabledOnIntegrationTest.ArtifactType.NATIVE_BINARY
449
}
450
)
451
void testContainerNetworking() {
452
// Test implementation
453
}
454
}
455
```