Common test utilities and framework for Quarkus applications, providing core testing infrastructure including application launchers, test isolation, configuration management, and integration with REST Assured for HTTP testing
—
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.
Manages temporary system property changes with automatic restoration, essential for tests that need to modify global system state.
public class RestorableSystemProperties implements Closeable {
public static RestorableSystemProperties setProperties(
Map<String, String> props,
String... additionalKeysToSave
) {}
public void close() {}
}Usage Example:
public class SystemPropertyTest {
@Test
public void testWithCustomProperties() {
// Save current system properties and set test values
try (RestorableSystemProperties restore = RestorableSystemProperties.setProperties(
Map.of(
"app.environment", "test",
"database.url", "jdbc:h2:mem:test",
"logging.level", "DEBUG"
),
"user.home", "java.version" // Additional properties to preserve
)) {
// Test logic that depends on system properties
assertEquals("test", System.getProperty("app.environment"));
assertEquals("jdbc:h2:mem:test", System.getProperty("database.url"));
// Verify application behavior with test properties
ApplicationConfig config = new ApplicationConfig();
assertTrue(config.isTestEnvironment());
} // Properties automatically restored here
// Verify properties are restored
assertNotEquals("test", System.getProperty("app.environment"));
}
@Test
public void testNestedPropertyChanges() {
try (RestorableSystemProperties outer = RestorableSystemProperties.setProperties(
Map.of("level", "outer"))) {
assertEquals("outer", System.getProperty("level"));
try (RestorableSystemProperties inner = RestorableSystemProperties.setProperties(
Map.of("level", "inner"))) {
assertEquals("inner", System.getProperty("level"));
} // Inner properties restored
assertEquals("outer", System.getProperty("level"));
} // Outer properties restored
}
}Utility for mapping test and application class directories, essential for build tool integration and resource location.
public class PathTestHelper {
public static Path getTestClassesLocation(Class<?> testClass) {}
public static Path getTestClassesLocation(Class<?> requiredTestClass, CuratedApplication curatedApplication) {}
public static Path getAppClassLocationForTestLocation(Path testClassLocationPath) {}
public static Path getResourcesForClassesDirOrNull(Path classesDir, String name) {}
public static boolean isTestClass(String className, ClassLoader classLoader, Path testLocation) {}
public static Path getProjectBuildDir(Path projectRoot, Path testLocation) {}
}Usage Examples:
public class PathTestHelperTest {
@Test
public void testClassLocationMapping() {
// Get test class location
Path testLocation = PathTestHelper.getTestClassesLocation(this.getClass());
System.out.println("Test classes at: " + testLocation);
// Map to corresponding application classes
Path appLocation = PathTestHelper.getAppClassLocationForTestLocation(testLocation);
System.out.println("App classes at: " + appLocation);
// Verify paths exist
assertTrue(Files.exists(testLocation));
assertTrue(Files.exists(appLocation));
}
@Test
public void testResourceLocation() {
Path testClassesDir = PathTestHelper.getTestClassesLocation(this.getClass());
// Find test resources
Path testResources = PathTestHelper.getResourcesForClassesDirOrNull(testClassesDir, "test");
if (testResources != null) {
assertTrue(Files.exists(testResources));
System.out.println("Test resources at: " + testResources);
}
}
@Test
public void testClassTypeDetection() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Path testLocation = PathTestHelper.getTestClassesLocation(this.getClass());
// Check if classes are test classes
assertTrue(PathTestHelper.isTestClass(
"com.example.MyTest", classLoader, testLocation));
assertFalse(PathTestHelper.isTestClass(
"com.example.MyService", classLoader, testLocation));
}
@Test
public void testProjectBuildDirectory() {
Path projectRoot = Paths.get(".");
Path testLocation = PathTestHelper.getTestClassesLocation(this.getClass());
Path buildDir = PathTestHelper.getProjectBuildDir(projectRoot, testLocation);
System.out.println("Build directory: " + buildDir);
// Verify build directory structure
assertTrue(Files.exists(buildDir));
assertTrue(Files.exists(buildDir.resolve("classes")));
assertTrue(Files.exists(buildDir.resolve("test-classes")));
}
}Manages test scope setup and teardown via SPI, providing hooks for test lifecycle management.
public class TestScopeManager {
public static void setup(boolean isIntegrationTest) {}
public static void tearDown(boolean isIntegrationTest) {}
}Usage in Custom Test Extensions:
public class CustomTestExtension implements BeforeAllCallback, AfterAllCallback {
@Override
public void beforeAll(ExtensionContext context) {
boolean isIntegrationTest = context.getTestClass()
.map(cls -> cls.isAnnotationPresent(QuarkusIntegrationTest.class))
.orElse(false);
TestScopeManager.setup(isIntegrationTest);
if (isIntegrationTest) {
System.out.println("Setting up integration test environment");
// Additional integration test setup
} else {
System.out.println("Setting up unit test environment");
// Unit test specific setup
}
}
@Override
public void afterAll(ExtensionContext context) {
boolean isIntegrationTest = context.getTestClass()
.map(cls -> cls.isAnnotationPresent(QuarkusIntegrationTest.class))
.orElse(false);
TestScopeManager.tearDown(isIntegrationTest);
System.out.println("Test scope cleanup completed");
}
}
// Usage in test
@ExtendWith(CustomTestExtension.class)
public class ManagedScopeTest {
@Test
public void testWithManagedScope() {
// Test logic - scope is automatically managed
assertTrue(true);
}
}Utility for finding annotations with inheritance support, useful for framework integration and custom annotation processing.
public class AnnotationUtils {
public static <A extends Annotation> Optional<AnnotationContainer<A>> findAnnotation(
AnnotatedElement element,
Class<A> annotationType
) {}
}
public class AnnotationContainer<A extends Annotation> {
public AnnotationContainer(AnnotatedElement element, A annotation) {}
public AnnotatedElement getElement() {}
public A getAnnotation() {}
}Usage Examples:
public class AnnotationUtilsTest {
@Test
public void testAnnotationDiscovery() {
// Find annotation on class with inheritance
Optional<AnnotationContainer<QuarkusTestResource>> container =
AnnotationUtils.findAnnotation(MyTestClass.class, QuarkusTestResource.class);
if (container.isPresent()) {
QuarkusTestResource annotation = container.get().getAnnotation();
AnnotatedElement element = container.get().getElement();
System.out.println("Found @QuarkusTestResource on: " + element);
System.out.println("Resource class: " + annotation.value().getSimpleName());
}
}
@Test
public void testMethodAnnotationSearch() {
Method testMethod = ReflectionUtils.findMethod(MyTestClass.class, "testMethod");
Optional<AnnotationContainer<TestTransaction>> container =
AnnotationUtils.findAnnotation(testMethod, TestTransaction.class);
assertTrue(container.isPresent(), "Method should have @TestTransaction");
}
@Test
public void testFieldAnnotationSearch() throws NoSuchFieldException {
Field testField = MyTestClass.class.getDeclaredField("injectedService");
Optional<AnnotationContainer<InjectMock>> container =
AnnotationUtils.findAnnotation(testField, InjectMock.class);
assertTrue(container.isPresent(), "Field should have @InjectMock");
}
}
// Example test class for annotation discovery
@QuarkusTestResource(DatabaseTestResource.class)
public class MyTestClass {
@InjectMock
UserService injectedService;
@Test
@TestTransaction
public void testMethod() {
// Test implementation
}
}Building custom test frameworks using the utilities:
public class CustomTestFramework {
private final Map<String, Object> testContext = new HashMap<>();
public void setupTest(Class<?> testClass) {
// Use PathTestHelper for resource location
Path testClassLocation = PathTestHelper.getTestClassesLocation(testClass);
Path resourcesPath = PathTestHelper.getResourcesForClassesDirOrNull(testClassLocation, "test");
testContext.put("testClassLocation", testClassLocation);
testContext.put("resourcesPath", resourcesPath);
// Setup test scope
boolean isIntegrationTest = AnnotationUtils
.findAnnotation(testClass, QuarkusIntegrationTest.class)
.isPresent();
TestScopeManager.setup(isIntegrationTest);
testContext.put("isIntegrationTest", isIntegrationTest);
// Configure system properties
Map<String, String> testProperties = extractTestProperties(testClass);
RestorableSystemProperties restorableProps =
RestorableSystemProperties.setProperties(testProperties);
testContext.put("restorableProperties", restorableProps);
}
public void tearDownTest() {
// Restore system properties
RestorableSystemProperties restorableProps =
(RestorableSystemProperties) testContext.get("restorableProperties");
if (restorableProps != null) {
restorableProps.close();
}
// Tear down test scope
boolean isIntegrationTest = (boolean) testContext.get("isIntegrationTest");
TestScopeManager.tearDown(isIntegrationTest);
testContext.clear();
}
private Map<String, String> extractTestProperties(Class<?> testClass) {
Map<String, String> properties = new HashMap<>();
// Look for custom annotation with properties
Optional<AnnotationContainer<TestProperties>> container =
AnnotationUtils.findAnnotation(testClass, TestProperties.class);
if (container.isPresent()) {
TestProperties annotation = container.get().getAnnotation();
for (TestProperty prop : annotation.value()) {
properties.put(prop.name(), prop.value());
}
}
return properties;
}
}
// Custom annotations for the framework
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestProperties {
TestProperty[] value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestProperty {
String name();
String value();
}Using path utilities for build tool integration:
public class BuildToolIntegration {
public static void generateTestReport(Class<?> testClass) {
Path testLocation = PathTestHelper.getTestClassesLocation(testClass);
Path projectRoot = testLocation.getParent().getParent(); // Assume standard layout
Path buildDir = PathTestHelper.getProjectBuildDir(projectRoot, testLocation);
Path reportsDir = buildDir.resolve("reports").resolve("tests");
try {
Files.createDirectories(reportsDir);
Path reportFile = reportsDir.resolve("test-report.html");
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(reportFile))) {
writer.println("<html><body>");
writer.println("<h1>Test Report for " + testClass.getSimpleName() + "</h1>");
writer.println("<p>Test location: " + testLocation + "</p>");
writer.println("<p>Build directory: " + buildDir + "</p>");
writer.println("</body></html>");
}
System.out.println("Test report generated: " + reportFile);
} catch (IOException e) {
System.err.println("Failed to generate test report: " + e.getMessage());
}
}
}Advanced configuration management using system properties:
public class ConfigurationManager {
private static final Map<String, RestorableSystemProperties> activeConfigurations =
new ConcurrentHashMap<>();
public static String setupConfiguration(String configName, Map<String, String> properties) {
String configId = configName + "-" + System.currentTimeMillis();
RestorableSystemProperties restore = RestorableSystemProperties.setProperties(
properties,
// Preserve important system properties
"java.home", "user.home", "java.class.path"
);
activeConfigurations.put(configId, restore);
return configId;
}
public static void restoreConfiguration(String configId) {
RestorableSystemProperties restore = activeConfigurations.remove(configId);
if (restore != null) {
restore.close();
}
}
public static void restoreAllConfigurations() {
activeConfigurations.values().forEach(RestorableSystemProperties::close);
activeConfigurations.clear();
}
// Usage in test lifecycle
@BeforeEach
public void setupTestConfig() {
Map<String, String> testConfig = Map.of(
"app.environment", "test",
"database.type", "h2",
"logging.level.com.example", "DEBUG"
);
String configId = ConfigurationManager.setupConfiguration("test", testConfig);
// Store configId for cleanup
}
@AfterEach
public void cleanupTestConfig() {
ConfigurationManager.restoreAllConfigurations();
}
}Install with Tessl CLI
npx tessl i tessl/maven-io-quarkus--quarkus-test-common