CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkus--quarkus-test-common

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

Pending
Overview
Eval results
Files

utilities.mddocs/

Utilities

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.

Capabilities

RestorableSystemProperties Class

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
    }
}

PathTestHelper Class

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")));
    }
}

TestScopeManager Class

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);
    }
}

AnnotationUtils Class

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
    }
}

Advanced Usage Patterns

Custom Test Framework Integration

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();
}

Build Tool Integration

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());
        }
    }
}

Configuration Management

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

docs

http-testing.md

index.md

launchers.md

test-annotations.md

test-context.md

test-resources.md

utilities.md

tile.json