A runner for unit tests, intended for testing Quarkus rather than for end user consumption.
—
Support for customizing Quarkus build chains during testing, including build steps, producers, and consumers for comprehensive build testing.
Abstract base class for creating custom build steps in production mode tests.
public abstract class ProdModeTestBuildStep implements BuildStep {
public ProdModeTestBuildStep(Map<String, Object> testContext);
public Map<String, Object> getTestContext();
}Consumer for customizing build chains in production mode tests.
public class ProdModeTestBuildChainBuilderConsumer implements Consumer<BuildChainBuilder> {
public ProdModeTestBuildChainBuilderConsumer(String buildStepClassName,
List<String> producesClassNames, List<String> consumesClassNames,
Map<String, Object> testContext);
public void accept(BuildChainBuilder builder);
}Function for producing build chain customizers.
public class ProdModeTestBuildChainCustomizerProducer implements Function<Map<String, Object>, List<Consumer<BuildChainBuilder>>> {
public List<Consumer<BuildChainBuilder>> apply(Map<String, Object> testContext);
}import io.quarkus.test.ProdModeTestBuildStep;
import io.quarkus.deployment.builditem.BuildItem;
import io.quarkus.deployment.BuildContext;
public class MyCustomBuildStep extends ProdModeTestBuildStep {
public MyCustomBuildStep(Map<String, Object> testContext) {
super(testContext);
}
@Override
public void execute(BuildContext context) {
// Access test context
Map<String, Object> testContext = getTestContext();
String customValue = (String) testContext.get("customKey");
// Perform custom build logic
MyBuildItem buildItem = new MyBuildItem(customValue);
context.produce(buildItem);
}
}
// Custom build item
public class MyBuildItem extends BuildItem {
private final String value;
public MyBuildItem(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}import io.quarkus.test.QuarkusProdModeTest;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.api.Test;
public class BuildChainCustomizationTest {
@RegisterExtension
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
.withApplicationRoot(jar -> jar.addClasses(MyService.class))
.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(
MyCustomBuildStep.class,
List.of(MyBuildItem.class), // Produces
List.of(ApplicationArchivesBuildItem.class) // Consumes
));
@Test
public void testCustomBuildStep() {
// Test that custom build step was executed
// Build artifacts will include MyBuildItem
}
}public class ComplexBuildStep extends ProdModeTestBuildStep {
public ComplexBuildStep(Map<String, Object> testContext) {
super(testContext);
}
@Override
public void execute(BuildContext context) {
// Consume required build items
ApplicationArchivesBuildItem archives = context.consume(ApplicationArchivesBuildItem.class);
FeatureBuildItem features = context.consume(FeatureBuildItem.class);
// Access test context for configuration
Map<String, Object> testContext = getTestContext();
boolean enableFeature = (Boolean) testContext.getOrDefault("enableFeature", false);
if (enableFeature) {
// Produce custom build items
context.produce(new CustomFeatureBuildItem());
context.produce(new AdditionalBeanBuildItem(MyCustomBean.class));
}
// Modify existing build items if needed
for (ApplicationArchive archive : archives.getAllApplicationArchives()) {
// Process archive
}
}
}public class FirstBuildStep extends ProdModeTestBuildStep {
public FirstBuildStep(Map<String, Object> testContext) {
super(testContext);
}
@Override
public void execute(BuildContext context) {
context.produce(new IntermediateBuildItem("processed-data"));
}
}
public class SecondBuildStep extends ProdModeTestBuildStep {
public SecondBuildStep(Map<String, Object> testContext) {
super(testContext);
}
@Override
public void execute(BuildContext context) {
IntermediateBuildItem intermediate = context.consume(IntermediateBuildItem.class);
String processedData = intermediate.getData();
// Final processing
context.produce(new FinalBuildItem(processedData + "-final"));
}
}
// Test with multiple build steps
@RegisterExtension
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
.withApplicationRoot(jar -> jar.addClasses(MyService.class))
.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(
FirstBuildStep.class,
List.of(IntermediateBuildItem.class),
List.of()
))
.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(
SecondBuildStep.class,
List.of(FinalBuildItem.class),
List.of(IntermediateBuildItem.class)
));public class ConditionalBuildStep extends ProdModeTestBuildStep {
public ConditionalBuildStep(Map<String, Object> testContext) {
super(testContext);
}
@Override
public void execute(BuildContext context) {
Map<String, Object> testContext = getTestContext();
// Check conditions from test context
String environment = (String) testContext.get("environment");
boolean debugMode = (Boolean) testContext.getOrDefault("debug", false);
if ("production".equals(environment)) {
context.produce(new ProductionOptimizationBuildItem());
} else if ("development".equals(environment)) {
context.produce(new DevelopmentToolsBuildItem());
}
if (debugMode) {
context.produce(new DebugInfoBuildItem());
}
}
}
// Usage in test
@RegisterExtension
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
.withApplicationRoot(jar -> jar.addClasses(MyService.class))
.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(
ConditionalBuildStep.class,
List.of(ProductionOptimizationBuildItem.class, DevelopmentToolsBuildItem.class, DebugInfoBuildItem.class),
List.of()
));
@Test
public void testProductionMode() {
// Test context will be passed to build step
// Build step will produce ProductionOptimizationBuildItem
}public class ResourceProcessingBuildStep extends ProdModeTestBuildStep {
public ResourceProcessingBuildStep(Map<String, Object> testContext) {
super(testContext);
}
@Override
public void execute(BuildContext context) {
ApplicationArchivesBuildItem archives = context.consume(ApplicationArchivesBuildItem.class);
for (ApplicationArchive archive : archives.getAllApplicationArchives()) {
// Process resources in the archive
Path resourcesPath = archive.getArchiveRoot().resolve("META-INF/resources");
if (Files.exists(resourcesPath)) {
try {
Files.walk(resourcesPath)
.filter(Files::isRegularFile)
.forEach(this::processResource);
} catch (IOException e) {
throw new RuntimeException("Failed to process resources", e);
}
}
}
// Produce build item indicating resources were processed
context.produce(new ProcessedResourcesBuildItem());
}
private void processResource(Path resourcePath) {
// Custom resource processing logic
Map<String, Object> testContext = getTestContext();
String processingMode = (String) testContext.get("resourceProcessingMode");
// Process based on mode
if ("minify".equals(processingMode)) {
// Minify resource
} else if ("optimize".equals(processingMode)) {
// Optimize resource
}
}
}@Test
public void testBuildStepExecution() {
// Test that custom build steps were executed correctly
// This can be verified through:
// 1. Checking build logs
String buildOutput = config.getStartupConsoleOutput();
assertTrue(buildOutput.contains("MyCustomBuildStep executed"));
// 2. Examining build artifacts (if accessible)
// 3. Testing runtime behavior that depends on build step output
// 4. Using test context to pass verification flags
}
@Test
public void testBuildStepWithContext() {
// Test context is automatically passed to build steps
// You can verify build step behavior by examining the results
// The build step can access test context and modify behavior accordingly
// This allows for parameterized build testing
}// Simple build item
public class MyBuildItem extends BuildItem {
private final String data;
public MyBuildItem(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
// Complex build item with multiple properties
public class ConfigurationBuildItem extends BuildItem {
private final Map<String, String> properties;
private final List<String> features;
public ConfigurationBuildItem(Map<String, String> properties, List<String> features) {
this.properties = Collections.unmodifiableMap(properties);
this.features = Collections.unmodifiableList(features);
}
public Map<String, String> getProperties() {
return properties;
}
public List<String> getFeatures() {
return features;
}
}Install with Tessl CLI
npx tessl i tessl/maven-io-quarkus--quarkus-junit5-internal