0
# Conditional Execution
1
2
Rich set of built-in conditions for controlling test execution based on runtime environment, system properties, and custom logic. Tests can be enabled or disabled dynamically based on various criteria.
3
4
## Imports
5
6
```java
7
import org.junit.jupiter.api.condition.*;
8
import static org.junit.jupiter.api.Assertions.*;
9
```
10
11
## Capabilities
12
13
### Operating System Conditions
14
15
Enable or disable tests based on the operating system.
16
17
```java { .api }
18
/**
19
* Enable test on specific operating systems
20
*/
21
@Target({ElementType.TYPE, ElementType.METHOD})
22
@Retention(RetentionPolicy.RUNTIME)
23
@ExtendWith(EnabledOnOsCondition.class)
24
@interface EnabledOnOs {
25
OS[] value();
26
String disabledReason() default "";
27
}
28
29
/**
30
* Disable test on specific operating systems
31
*/
32
@Target({ElementType.TYPE, ElementType.METHOD})
33
@Retention(RetentionPolicy.RUNTIME)
34
@ExtendWith(DisabledOnOsCondition.class)
35
@interface DisabledOnOs {
36
OS[] value();
37
String disabledReason() default "";
38
}
39
40
/**
41
* Operating system enumeration
42
*/
43
enum OS {
44
LINUX,
45
MAC,
46
WINDOWS,
47
AIX,
48
SOLARIS,
49
OTHER
50
}
51
```
52
53
**Usage Examples:**
54
55
```java
56
class OsSpecificTest {
57
58
@Test
59
@EnabledOnOs(OS.LINUX)
60
void testOnLinuxOnly() {
61
assertEquals("/", File.separator);
62
}
63
64
@Test
65
@EnabledOnOs({OS.WINDOWS, OS.MAC})
66
void testOnWindowsOrMac() {
67
assertNotEquals("/", File.separator);
68
}
69
70
@Test
71
@DisabledOnOs(value = OS.WINDOWS, disabledReason = "Windows path handling differs")
72
void testUnixPaths() {
73
assertTrue(Paths.get("/usr/local").isAbsolute());
74
}
75
}
76
```
77
78
### Java Runtime Environment Conditions
79
80
Control execution based on JRE version.
81
82
```java { .api }
83
/**
84
* Enable test on specific JRE versions
85
*/
86
@Target({ElementType.TYPE, ElementType.METHOD})
87
@Retention(RetentionPolicy.RUNTIME)
88
@ExtendWith(EnabledOnJreCondition.class)
89
@interface EnabledOnJre {
90
JRE[] value();
91
String disabledReason() default "";
92
}
93
94
/**
95
* Disable test on specific JRE versions
96
*/
97
@Target({ElementType.TYPE, ElementType.METHOD})
98
@Retention(RetentionPolicy.RUNTIME)
99
@ExtendWith(DisabledOnJreCondition.class)
100
@interface DisabledOnJre {
101
JRE[] value();
102
String disabledReason() default "";
103
}
104
105
/**
106
* Enable test for JRE version ranges
107
*/
108
@Target({ElementType.TYPE, ElementType.METHOD})
109
@Retention(RetentionPolicy.RUNTIME)
110
@ExtendWith(EnabledForJreRangeCondition.class)
111
@interface EnabledForJreRange {
112
JRE min() default JRE.JAVA_8;
113
JRE max() default JRE.OTHER;
114
String disabledReason() default "";
115
}
116
117
/**
118
* Disable test for JRE version ranges
119
*/
120
@Target({ElementType.TYPE, ElementType.METHOD})
121
@Retention(RetentionPolicy.RUNTIME)
122
@ExtendWith(DisabledForJreRangeCondition.class)
123
@interface DisabledForJreRange {
124
JRE min() default JRE.JAVA_8;
125
JRE max() default JRE.OTHER;
126
String disabledReason() default "";
127
}
128
```
129
130
**Usage Examples:**
131
132
```java
133
class JreSpecificTest {
134
135
@Test
136
@EnabledOnJre(JRE.JAVA_8)
137
void testOnJava8Only() {
138
// Java 8 specific functionality
139
}
140
141
@Test
142
@EnabledForJreRange(min = JRE.JAVA_11, max = JRE.JAVA_17)
143
void testOnJava11To17() {
144
// Features available in Java 11-17
145
}
146
147
@Test
148
@DisabledOnJre(value = JRE.JAVA_8, disabledReason = "Lambda syntax not supported")
149
void testWithModernJavaFeatures() {
150
// Modern Java features
151
var list = List.of("item1", "item2");
152
assertFalse(list.isEmpty());
153
}
154
}
155
```
156
157
### System Property Conditions
158
159
Execute tests conditionally based on system properties.
160
161
```java { .api }
162
/**
163
* Enable test if system property matches
164
*/
165
@Target({ElementType.TYPE, ElementType.METHOD})
166
@Retention(RetentionPolicy.RUNTIME)
167
@Repeatable(EnabledIfSystemProperties.class)
168
@ExtendWith(EnabledIfSystemPropertyCondition.class)
169
@interface EnabledIfSystemProperty {
170
String named();
171
String matches();
172
String disabledReason() default "";
173
}
174
175
/**
176
* Container for multiple system property conditions
177
*/
178
@Target({ElementType.TYPE, ElementType.METHOD})
179
@Retention(RetentionPolicy.RUNTIME)
180
@ExtendWith(EnabledIfSystemPropertyCondition.class)
181
@interface EnabledIfSystemProperties {
182
EnabledIfSystemProperty[] value();
183
}
184
185
/**
186
* Disable test if system property matches
187
*/
188
@Target({ElementType.TYPE, ElementType.METHOD})
189
@Retention(RetentionPolicy.RUNTIME)
190
@Repeatable(DisabledIfSystemProperties.class)
191
@ExtendWith(DisabledIfSystemPropertyCondition.class)
192
@interface DisabledIfSystemProperty {
193
String named();
194
String matches();
195
String disabledReason() default "";
196
}
197
198
/**
199
* Container for multiple system property conditions
200
*/
201
@Target({ElementType.TYPE, ElementType.METHOD})
202
@Retention(RetentionPolicy.RUNTIME)
203
@ExtendWith(DisabledIfSystemPropertyCondition.class)
204
@interface DisabledIfSystemProperties {
205
DisabledIfSystemProperty[] value();
206
}
207
```
208
209
**Usage Examples:**
210
211
```java
212
class SystemPropertyTest {
213
214
@Test
215
@EnabledIfSystemProperty(named = "env", matches = "dev")
216
void testInDevelopmentOnly() {
217
// Development environment specific test
218
}
219
220
@Test
221
@EnabledIfSystemProperty(named = "debug", matches = "true")
222
void testWithDebugEnabled() {
223
// Debug mode specific test
224
}
225
226
@Test
227
@DisabledIfSystemProperty(named = "ci", matches = "true",
228
disabledReason = "Flaky in CI environment")
229
void testDisabledInCI() {
230
// Test that's unreliable in CI
231
}
232
233
@Test
234
@EnabledIfSystemProperties({
235
@EnabledIfSystemProperty(named = "env", matches = "test"),
236
@EnabledIfSystemProperty(named = "db.enabled", matches = "true")
237
})
238
void testWithMultipleProperties() {
239
// Test requiring multiple system properties
240
}
241
}
242
```
243
244
### Environment Variable Conditions
245
246
Execute tests conditionally based on environment variables.
247
248
```java { .api }
249
/**
250
* Enable test if environment variable matches
251
*/
252
@Target({ElementType.TYPE, ElementType.METHOD})
253
@Retention(RetentionPolicy.RUNTIME)
254
@Repeatable(EnabledIfEnvironmentVariables.class)
255
@ExtendWith(EnabledIfEnvironmentVariableCondition.class)
256
@interface EnabledIfEnvironmentVariable {
257
String named();
258
String matches();
259
String disabledReason() default "";
260
}
261
262
/**
263
* Container for multiple environment variable conditions
264
*/
265
@Target({ElementType.TYPE, ElementType.METHOD})
266
@Retention(RetentionPolicy.RUNTIME)
267
@ExtendWith(EnabledIfEnvironmentVariableCondition.class)
268
@interface EnabledIfEnvironmentVariables {
269
EnabledIfEnvironmentVariable[] value();
270
}
271
272
/**
273
* Disable test if environment variable matches
274
*/
275
@Target({ElementType.TYPE, ElementType.METHOD})
276
@Retention(RetentionPolicy.RUNTIME)
277
@Repeatable(DisabledIfEnvironmentVariables.class)
278
@ExtendWith(DisabledIfEnvironmentVariableCondition.class)
279
@interface DisabledIfEnvironmentVariable {
280
String named();
281
String matches();
282
String disabledReason() default "";
283
}
284
285
/**
286
* Container for multiple environment variable conditions
287
*/
288
@Target({ElementType.TYPE, ElementType.METHOD})
289
@Retention(RetentionPolicy.RUNTIME)
290
@ExtendWith(DisabledIfEnvironmentVariableCondition.class)
291
@interface DisabledIfEnvironmentVariables {
292
DisabledIfEnvironmentVariable[] value();
293
}
294
```
295
296
**Usage Examples:**
297
298
```java
299
class EnvironmentVariableTest {
300
301
@Test
302
@EnabledIfEnvironmentVariable(named = "ENV", matches = "production")
303
void testInProductionOnly() {
304
// Production-specific test
305
}
306
307
@Test
308
@EnabledIfEnvironmentVariable(named = "DATABASE_URL", matches = ".*localhost.*")
309
void testWithLocalDatabase() {
310
// Test requiring local database
311
}
312
313
@Test
314
@DisabledIfEnvironmentVariable(named = "SKIP_SLOW_TESTS", matches = "true")
315
void slowTest() throws InterruptedException {
316
Thread.sleep(5000);
317
assertTrue(true);
318
}
319
}
320
```
321
322
### Custom Condition Methods
323
324
Execute tests based on custom boolean methods.
325
326
```java { .api }
327
/**
328
* Enable test if custom condition method returns true
329
*/
330
@Target({ElementType.TYPE, ElementType.METHOD})
331
@Retention(RetentionPolicy.RUNTIME)
332
@ExtendWith(EnabledIfCondition.class)
333
@interface EnabledIf {
334
/**
335
* Method name that returns boolean
336
*/
337
String value();
338
String disabledReason() default "";
339
}
340
341
/**
342
* Disable test if custom condition method returns true
343
*/
344
@Target({ElementType.TYPE, ElementType.METHOD})
345
@Retention(RetentionPolicy.RUNTIME)
346
@ExtendWith(DisabledIfCondition.class)
347
@interface DisabledIf {
348
/**
349
* Method name that returns boolean
350
*/
351
String value();
352
String disabledReason() default "";
353
}
354
```
355
356
**Usage Examples:**
357
358
```java
359
class CustomConditionTest {
360
361
@Test
362
@EnabledIf("isExternalServiceAvailable")
363
void testWithExternalService() {
364
// Test that requires external service
365
}
366
367
@Test
368
@DisabledIf("isWeekend")
369
void testDisabledOnWeekends() {
370
// Test that shouldn't run on weekends
371
}
372
373
static boolean isExternalServiceAvailable() {
374
try {
375
// Check if external service is reachable
376
URL url = new URL("http://api.example.com/health");
377
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
378
connection.setRequestMethod("GET");
379
connection.setConnectTimeout(1000);
380
return connection.getResponseCode() == 200;
381
} catch (Exception e) {
382
return false;
383
}
384
}
385
386
static boolean isWeekend() {
387
DayOfWeek today = LocalDate.now().getDayOfWeek();
388
return today == DayOfWeek.SATURDAY || today == DayOfWeek.SUNDAY;
389
}
390
}
391
```
392
393
### GraalVM Native Image Conditions
394
395
Control execution in GraalVM native image contexts.
396
397
```java { .api }
398
/**
399
* Enable test only in GraalVM native image
400
*/
401
@Target({ElementType.TYPE, ElementType.METHOD})
402
@Retention(RetentionPolicy.RUNTIME)
403
@interface EnabledInNativeImage {
404
String disabledReason() default "";
405
}
406
407
/**
408
* Disable test in GraalVM native image
409
*/
410
@Target({ElementType.TYPE, ElementType.METHOD})
411
@Retention(RetentionPolicy.RUNTIME)
412
@interface DisabledInNativeImage {
413
String disabledReason() default "";
414
}
415
```
416
417
**Usage Examples:**
418
419
```java
420
class NativeImageTest {
421
422
@Test
423
@EnabledInNativeImage
424
void testNativeImageSpecificBehavior() {
425
// Test behavior specific to native image
426
}
427
428
@Test
429
@DisabledInNativeImage(disabledReason = "Reflection not available in native image")
430
void testWithReflection() {
431
// Test using reflection APIs
432
Class<?> clazz = String.class;
433
Method[] methods = clazz.getDeclaredMethods();
434
assertTrue(methods.length > 0);
435
}
436
}
437
```