0
# Utilities
1
2
Helper classes for common testing scenarios including path mapping, system property management, annotation processing, and test scope management. These utilities provide essential functionality for advanced test scenarios and framework integration.
3
4
## Capabilities
5
6
### RestorableSystemProperties Class
7
8
Manages temporary system property changes with automatic restoration, essential for tests that need to modify global system state.
9
10
```java { .api }
11
public class RestorableSystemProperties implements Closeable {
12
public static RestorableSystemProperties setProperties(
13
Map<String, String> props,
14
String... additionalKeysToSave
15
) {}
16
public void close() {}
17
}
18
```
19
20
**Usage Example:**
21
```java
22
public class SystemPropertyTest {
23
@Test
24
public void testWithCustomProperties() {
25
// Save current system properties and set test values
26
try (RestorableSystemProperties restore = RestorableSystemProperties.setProperties(
27
Map.of(
28
"app.environment", "test",
29
"database.url", "jdbc:h2:mem:test",
30
"logging.level", "DEBUG"
31
),
32
"user.home", "java.version" // Additional properties to preserve
33
)) {
34
// Test logic that depends on system properties
35
assertEquals("test", System.getProperty("app.environment"));
36
assertEquals("jdbc:h2:mem:test", System.getProperty("database.url"));
37
38
// Verify application behavior with test properties
39
ApplicationConfig config = new ApplicationConfig();
40
assertTrue(config.isTestEnvironment());
41
42
} // Properties automatically restored here
43
44
// Verify properties are restored
45
assertNotEquals("test", System.getProperty("app.environment"));
46
}
47
48
@Test
49
public void testNestedPropertyChanges() {
50
try (RestorableSystemProperties outer = RestorableSystemProperties.setProperties(
51
Map.of("level", "outer"))) {
52
53
assertEquals("outer", System.getProperty("level"));
54
55
try (RestorableSystemProperties inner = RestorableSystemProperties.setProperties(
56
Map.of("level", "inner"))) {
57
58
assertEquals("inner", System.getProperty("level"));
59
60
} // Inner properties restored
61
62
assertEquals("outer", System.getProperty("level"));
63
64
} // Outer properties restored
65
}
66
}
67
```
68
69
### PathTestHelper Class
70
71
Utility for mapping test and application class directories, essential for build tool integration and resource location.
72
73
```java { .api }
74
public class PathTestHelper {
75
public static Path getTestClassesLocation(Class<?> testClass) {}
76
public static Path getTestClassesLocation(Class<?> requiredTestClass, CuratedApplication curatedApplication) {}
77
public static Path getAppClassLocationForTestLocation(Path testClassLocationPath) {}
78
public static Path getResourcesForClassesDirOrNull(Path classesDir, String name) {}
79
public static boolean isTestClass(String className, ClassLoader classLoader, Path testLocation) {}
80
public static Path getProjectBuildDir(Path projectRoot, Path testLocation) {}
81
}
82
```
83
84
**Usage Examples:**
85
```java
86
public class PathTestHelperTest {
87
@Test
88
public void testClassLocationMapping() {
89
// Get test class location
90
Path testLocation = PathTestHelper.getTestClassesLocation(this.getClass());
91
System.out.println("Test classes at: " + testLocation);
92
93
// Map to corresponding application classes
94
Path appLocation = PathTestHelper.getAppClassLocationForTestLocation(testLocation);
95
System.out.println("App classes at: " + appLocation);
96
97
// Verify paths exist
98
assertTrue(Files.exists(testLocation));
99
assertTrue(Files.exists(appLocation));
100
}
101
102
@Test
103
public void testResourceLocation() {
104
Path testClassesDir = PathTestHelper.getTestClassesLocation(this.getClass());
105
106
// Find test resources
107
Path testResources = PathTestHelper.getResourcesForClassesDirOrNull(testClassesDir, "test");
108
if (testResources != null) {
109
assertTrue(Files.exists(testResources));
110
System.out.println("Test resources at: " + testResources);
111
}
112
}
113
114
@Test
115
public void testClassTypeDetection() {
116
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
117
Path testLocation = PathTestHelper.getTestClassesLocation(this.getClass());
118
119
// Check if classes are test classes
120
assertTrue(PathTestHelper.isTestClass(
121
"com.example.MyTest", classLoader, testLocation));
122
123
assertFalse(PathTestHelper.isTestClass(
124
"com.example.MyService", classLoader, testLocation));
125
}
126
127
@Test
128
public void testProjectBuildDirectory() {
129
Path projectRoot = Paths.get(".");
130
Path testLocation = PathTestHelper.getTestClassesLocation(this.getClass());
131
132
Path buildDir = PathTestHelper.getProjectBuildDir(projectRoot, testLocation);
133
System.out.println("Build directory: " + buildDir);
134
135
// Verify build directory structure
136
assertTrue(Files.exists(buildDir));
137
assertTrue(Files.exists(buildDir.resolve("classes")));
138
assertTrue(Files.exists(buildDir.resolve("test-classes")));
139
}
140
}
141
```
142
143
### TestScopeManager Class
144
145
Manages test scope setup and teardown via SPI, providing hooks for test lifecycle management.
146
147
```java { .api }
148
public class TestScopeManager {
149
public static void setup(boolean isIntegrationTest) {}
150
public static void tearDown(boolean isIntegrationTest) {}
151
}
152
```
153
154
**Usage in Custom Test Extensions:**
155
```java
156
public class CustomTestExtension implements BeforeAllCallback, AfterAllCallback {
157
@Override
158
public void beforeAll(ExtensionContext context) {
159
boolean isIntegrationTest = context.getTestClass()
160
.map(cls -> cls.isAnnotationPresent(QuarkusIntegrationTest.class))
161
.orElse(false);
162
163
TestScopeManager.setup(isIntegrationTest);
164
165
if (isIntegrationTest) {
166
System.out.println("Setting up integration test environment");
167
// Additional integration test setup
168
} else {
169
System.out.println("Setting up unit test environment");
170
// Unit test specific setup
171
}
172
}
173
174
@Override
175
public void afterAll(ExtensionContext context) {
176
boolean isIntegrationTest = context.getTestClass()
177
.map(cls -> cls.isAnnotationPresent(QuarkusIntegrationTest.class))
178
.orElse(false);
179
180
TestScopeManager.tearDown(isIntegrationTest);
181
182
System.out.println("Test scope cleanup completed");
183
}
184
}
185
186
// Usage in test
187
@ExtendWith(CustomTestExtension.class)
188
public class ManagedScopeTest {
189
@Test
190
public void testWithManagedScope() {
191
// Test logic - scope is automatically managed
192
assertTrue(true);
193
}
194
}
195
```
196
197
### AnnotationUtils Class
198
199
Utility for finding annotations with inheritance support, useful for framework integration and custom annotation processing.
200
201
```java { .api }
202
public class AnnotationUtils {
203
public static <A extends Annotation> Optional<AnnotationContainer<A>> findAnnotation(
204
AnnotatedElement element,
205
Class<A> annotationType
206
) {}
207
}
208
209
public class AnnotationContainer<A extends Annotation> {
210
public AnnotationContainer(AnnotatedElement element, A annotation) {}
211
public AnnotatedElement getElement() {}
212
public A getAnnotation() {}
213
}
214
```
215
216
**Usage Examples:**
217
```java
218
public class AnnotationUtilsTest {
219
@Test
220
public void testAnnotationDiscovery() {
221
// Find annotation on class with inheritance
222
Optional<AnnotationContainer<QuarkusTestResource>> container =
223
AnnotationUtils.findAnnotation(MyTestClass.class, QuarkusTestResource.class);
224
225
if (container.isPresent()) {
226
QuarkusTestResource annotation = container.get().getAnnotation();
227
AnnotatedElement element = container.get().getElement();
228
229
System.out.println("Found @QuarkusTestResource on: " + element);
230
System.out.println("Resource class: " + annotation.value().getSimpleName());
231
}
232
}
233
234
@Test
235
public void testMethodAnnotationSearch() {
236
Method testMethod = ReflectionUtils.findMethod(MyTestClass.class, "testMethod");
237
238
Optional<AnnotationContainer<TestTransaction>> container =
239
AnnotationUtils.findAnnotation(testMethod, TestTransaction.class);
240
241
assertTrue(container.isPresent(), "Method should have @TestTransaction");
242
}
243
244
@Test
245
public void testFieldAnnotationSearch() throws NoSuchFieldException {
246
Field testField = MyTestClass.class.getDeclaredField("injectedService");
247
248
Optional<AnnotationContainer<InjectMock>> container =
249
AnnotationUtils.findAnnotation(testField, InjectMock.class);
250
251
assertTrue(container.isPresent(), "Field should have @InjectMock");
252
}
253
}
254
255
// Example test class for annotation discovery
256
@QuarkusTestResource(DatabaseTestResource.class)
257
public class MyTestClass {
258
@InjectMock
259
UserService injectedService;
260
261
@Test
262
@TestTransaction
263
public void testMethod() {
264
// Test implementation
265
}
266
}
267
```
268
269
## Advanced Usage Patterns
270
271
### Custom Test Framework Integration
272
273
Building custom test frameworks using the utilities:
274
275
```java
276
public class CustomTestFramework {
277
private final Map<String, Object> testContext = new HashMap<>();
278
279
public void setupTest(Class<?> testClass) {
280
// Use PathTestHelper for resource location
281
Path testClassLocation = PathTestHelper.getTestClassesLocation(testClass);
282
Path resourcesPath = PathTestHelper.getResourcesForClassesDirOrNull(testClassLocation, "test");
283
284
testContext.put("testClassLocation", testClassLocation);
285
testContext.put("resourcesPath", resourcesPath);
286
287
// Setup test scope
288
boolean isIntegrationTest = AnnotationUtils
289
.findAnnotation(testClass, QuarkusIntegrationTest.class)
290
.isPresent();
291
292
TestScopeManager.setup(isIntegrationTest);
293
testContext.put("isIntegrationTest", isIntegrationTest);
294
295
// Configure system properties
296
Map<String, String> testProperties = extractTestProperties(testClass);
297
RestorableSystemProperties restorableProps =
298
RestorableSystemProperties.setProperties(testProperties);
299
testContext.put("restorableProperties", restorableProps);
300
}
301
302
public void tearDownTest() {
303
// Restore system properties
304
RestorableSystemProperties restorableProps =
305
(RestorableSystemProperties) testContext.get("restorableProperties");
306
if (restorableProps != null) {
307
restorableProps.close();
308
}
309
310
// Tear down test scope
311
boolean isIntegrationTest = (boolean) testContext.get("isIntegrationTest");
312
TestScopeManager.tearDown(isIntegrationTest);
313
314
testContext.clear();
315
}
316
317
private Map<String, String> extractTestProperties(Class<?> testClass) {
318
Map<String, String> properties = new HashMap<>();
319
320
// Look for custom annotation with properties
321
Optional<AnnotationContainer<TestProperties>> container =
322
AnnotationUtils.findAnnotation(testClass, TestProperties.class);
323
324
if (container.isPresent()) {
325
TestProperties annotation = container.get().getAnnotation();
326
for (TestProperty prop : annotation.value()) {
327
properties.put(prop.name(), prop.value());
328
}
329
}
330
331
return properties;
332
}
333
}
334
335
// Custom annotations for the framework
336
@Target(ElementType.TYPE)
337
@Retention(RetentionPolicy.RUNTIME)
338
public @interface TestProperties {
339
TestProperty[] value();
340
}
341
342
@Target(ElementType.TYPE)
343
@Retention(RetentionPolicy.RUNTIME)
344
public @interface TestProperty {
345
String name();
346
String value();
347
}
348
```
349
350
### Build Tool Integration
351
352
Using path utilities for build tool integration:
353
354
```java
355
public class BuildToolIntegration {
356
public static void generateTestReport(Class<?> testClass) {
357
Path testLocation = PathTestHelper.getTestClassesLocation(testClass);
358
Path projectRoot = testLocation.getParent().getParent(); // Assume standard layout
359
Path buildDir = PathTestHelper.getProjectBuildDir(projectRoot, testLocation);
360
361
Path reportsDir = buildDir.resolve("reports").resolve("tests");
362
try {
363
Files.createDirectories(reportsDir);
364
365
Path reportFile = reportsDir.resolve("test-report.html");
366
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(reportFile))) {
367
writer.println("<html><body>");
368
writer.println("<h1>Test Report for " + testClass.getSimpleName() + "</h1>");
369
writer.println("<p>Test location: " + testLocation + "</p>");
370
writer.println("<p>Build directory: " + buildDir + "</p>");
371
writer.println("</body></html>");
372
}
373
374
System.out.println("Test report generated: " + reportFile);
375
376
} catch (IOException e) {
377
System.err.println("Failed to generate test report: " + e.getMessage());
378
}
379
}
380
}
381
```
382
383
### Configuration Management
384
385
Advanced configuration management using system properties:
386
387
```java
388
public class ConfigurationManager {
389
private static final Map<String, RestorableSystemProperties> activeConfigurations =
390
new ConcurrentHashMap<>();
391
392
public static String setupConfiguration(String configName, Map<String, String> properties) {
393
String configId = configName + "-" + System.currentTimeMillis();
394
395
RestorableSystemProperties restore = RestorableSystemProperties.setProperties(
396
properties,
397
// Preserve important system properties
398
"java.home", "user.home", "java.class.path"
399
);
400
401
activeConfigurations.put(configId, restore);
402
return configId;
403
}
404
405
public static void restoreConfiguration(String configId) {
406
RestorableSystemProperties restore = activeConfigurations.remove(configId);
407
if (restore != null) {
408
restore.close();
409
}
410
}
411
412
public static void restoreAllConfigurations() {
413
activeConfigurations.values().forEach(RestorableSystemProperties::close);
414
activeConfigurations.clear();
415
}
416
417
// Usage in test lifecycle
418
@BeforeEach
419
public void setupTestConfig() {
420
Map<String, String> testConfig = Map.of(
421
"app.environment", "test",
422
"database.type", "h2",
423
"logging.level.com.example", "DEBUG"
424
);
425
426
String configId = ConfigurationManager.setupConfiguration("test", testConfig);
427
// Store configId for cleanup
428
}
429
430
@AfterEach
431
public void cleanupTestConfig() {
432
ConfigurationManager.restoreAllConfigurations();
433
}
434
}
435
```