From 7a17e5bd89c3005aa64adde89e711adf10ed5672 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Mon, 9 Sep 2024 12:01:36 +0200 Subject: [PATCH] QuarkusUnitTest: addResource() and overwriteConfigProperty() fix --- .../java/io/quarkus/test/QuarkusUnitTest.java | 84 ++++++++++++++----- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusUnitTest.java b/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusUnitTest.java index 3e0b9bb4d57470..a246fead6ade5c 100644 --- a/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusUnitTest.java +++ b/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusUnitTest.java @@ -3,16 +3,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import java.io.FileNotFoundException; -import java.io.IOException; import java.io.InputStream; -import java.io.UncheckedIOException; +import java.io.StringReader; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -33,9 +30,13 @@ import java.util.logging.Handler; import java.util.logging.LogManager; import java.util.logging.LogRecord; +import java.util.stream.Collectors; import org.jboss.logmanager.Logger; +import org.jboss.shrinkwrap.api.Node; import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.Asset; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.jboss.shrinkwrap.api.exporter.ExplodedExporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.jupiter.api.extension.AfterAllCallback; @@ -87,6 +88,7 @@ public class QuarkusUnitTest public static final String THE_BUILD_WAS_EXPECTED_TO_FAIL = "The build was expected to fail"; private static final String APP_ROOT = "app-root"; + private static final String APPLICATION_PROPERTIES = "application.properties"; private static final Logger rootLogger; private Handler[] originalHandlers; @@ -348,9 +350,40 @@ private void exportArchives(Path deploymentDir, Class testClass) { archive.addClass(c); c = c.getSuperclass(); } + + Node applicationProperties = archive.get(APPLICATION_PROPERTIES); if (customApplicationProperties != null) { - archive.add(new PropertiesAsset(customApplicationProperties), "application.properties"); + if (applicationProperties != null) { + // We need to merge the existing "application.properties" asset and the overriden config properties + Properties mergedProperties = new Properties(); + Asset asset = applicationProperties.getAsset(); + if (asset instanceof StringAsset strAsset) { + mergedProperties.load(new StringReader(strAsset.getSource())); + } else { + try (InputStream in = asset.openStream()) { + mergedProperties.load(in); + } + } + // overrideConfigKey() takes precedence + customApplicationProperties.forEach(mergedProperties::put); + + if (Boolean.parseBoolean(System.getProperty("quarkus.test.log-merged-properties"))) { + System.out.println("Merged config properties:\n" + mergedProperties.entrySet().stream() + .map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("\n"))); + } else { + System.out.println( + "NOTE: overrideConfigKey() and application.properties were merged; use quarkus.test.log-merged-properties=true to list the specific values"); + } + + // MemoryMapArchiveBase#addAsset(ArchivePath,Asset) does not overwrite the existing node correctly + // https://github.com/shrinkwrap/shrinkwrap/issues/179 + archive.delete(APPLICATION_PROPERTIES); + archive.add(new PropertiesAsset(mergedProperties), APPLICATION_PROPERTIES); + } else { + archive.add(new PropertiesAsset(customApplicationProperties), APPLICATION_PROPERTIES); + } } + archive.as(ExplodedExporter.class).exportExplodedInto(deploymentDir.resolve(APP_ROOT).toFile()); for (JavaArchive dependency : additionalDependencies) { @@ -816,24 +849,37 @@ public QuarkusUnitTest setAfterUndeployListener(Runnable afterUndeployListener) return this; } + /** + * Add an {@code application.properties} asset loaded from the specified resource file in the test {@link JavaArchive}. + *

+ * Configuration properties added with {@link #overrideConfigKey(String, String)} take precedence over the properties from + * the specified resource file. + * + * @param resourceName + * @return the test configuration + */ public QuarkusUnitTest withConfigurationResource(String resourceName) { - if (customApplicationProperties == null) { - customApplicationProperties = new Properties(); - } - try { - URL systemResource = ClassLoader.getSystemResource(resourceName); - if (systemResource == null) { - throw new FileNotFoundException("Resource '" + resourceName + "' not found"); - } - try (InputStream in = systemResource.openStream()) { - customApplicationProperties.load(in); + final Supplier producer = archiveProducer; + setArchiveProducer(new Supplier() { + + @Override + public JavaArchive get() { + JavaArchive ret = producer == null ? ShrinkWrap.create(JavaArchive.class) : producer.get(); + ret.addAsResource(resourceName, APPLICATION_PROPERTIES); + return ret; } - return this; - } catch (IOException e) { - throw new UncheckedIOException("Could not load resource: '" + resourceName + "'", e); - } + }); + return this; } + /** + * Overriden configuration properties take precedence over an {@code application.properties} asset added in the test + * {@link JavaArchive}. + * + * @param propertyKey + * @param propertyValue + * @return the test configuration + */ public QuarkusUnitTest overrideConfigKey(final String propertyKey, final String propertyValue) { if (customApplicationProperties == null) { customApplicationProperties = new Properties();