From fd829921618526e1bd490decd242755ec29e443e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Champeau?= Date: Wed, 3 May 2023 17:57:28 +0200 Subject: [PATCH] Implement test resources property provider factory (#231) * Implement test resources property provider factory This commit introduces a new annotation, `@TestResourceProperties`, which can be applied on a test in order to tell that the test needs to resolve one or more test resource properties _before_ the application context is available. For example, with: ```java @MicronautTest @TestResourcesProperties( value = "redis.url" ) class SomeTest { ... } ``` Then the value of the `redis.url` property will automatically be fetched from the test resources service and made available as if it had been done in a `TestPropertyProvider`. The difference is that this without this annotation, it was required to call the test resources client directly in the provider, which was error prone. In particular, the `properties` argument of the `resolve` call are not easy to figure out. This annotation is therefore a convention to avoid having to call the client directly. However, in some cases it might be necessary to read a property in order to compute a different one which needs to be available in the test. This can be done by adding a `providers` argument to the annotation: ```java @TestResourcesProperties( value = "rabbitmq.uri", providers = RabbitTest.RabbitMQProvider.class ) class RabbitTest { // ... @ReflectiveAccess public static class RabbitMQProvider implements TestResourcesPropertyProvider { @Override public Map provide(Map testProperties) { String uri = (String) testProperties.get("rabbitmq.uri"); return Map.of( "rabbitmq.servers.product-cluster.port", String.valueOf(URI.create(uri).getPort()) ); } } } ``` The `TestResourcesPropertyProvider` type has access to all properties which are already resolved at the moment it is called, which includes the properties asked in `@TestResourcesProperties`. This should make the implementation of https://github.com/micronaut-projects/micronaut-nats/pull/321 easier. * Remove accidentally added files * Add javadocs * Add missing test * Make spotless happy * Add nullability annotations * Fix checkstyle and japicmp --- ...nal.test-resources-mntest-extension.gradle | 12 +++ ...ternal.test-resources-simple-module.gradle | 9 ++ gradle/libs.versions.toml | 6 +- settings.gradle | 16 ++++ .../build.gradle | 25 +++++ .../TestResourcesClientHolder.java | 96 +++++++++++++++++++ .../TestResourcesPropertiesFactory.java | 94 ++++++++++++++++++ .../TestResourcesPropertyProvider.java | 54 +++++++++++ .../annotation/TestResourcesProperties.java | 55 +++++++++++ ...t.test.support.TestPropertyProviderFactory | 1 + ...lesTestResourcesPropertyProvidersTest.java | 56 +++++++++++ ...pleTestResourcesPropertyProvidersTest.java | 46 +++++++++ .../TestResourcesPropertyProvidersTest.java | 54 +++++++++++ .../src/test/resources/application-test.yml | 12 +++ .../src/test/resources/logback.xml | 14 +++ .../FakeTestResourcesClient.java | 61 ++++++++++++ .../FakeTestResourcesClientInjector.java | 31 ++++++ .../extensions/testresources/SomeBean.java | 32 +++++++ ...it.platform.launcher.TestExecutionListener | 1 + 19 files changed, 674 insertions(+), 1 deletion(-) create mode 100644 buildSrc/src/main/groovy/io.micronaut.build.internal.test-resources-mntest-extension.gradle create mode 100644 buildSrc/src/main/groovy/io.micronaut.build.internal.test-resources-simple-module.gradle create mode 100644 test-resources-extensions/test-resources-extensions-core/build.gradle create mode 100644 test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesClientHolder.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesPropertiesFactory.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesPropertyProvider.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/annotation/TestResourcesProperties.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/main/resources/META-INF/services/io.micronaut.test.support.TestPropertyProviderFactory create mode 100644 test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/ConfigurationFilesTestResourcesPropertyProvidersTest.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/SimpleTestResourcesPropertyProvidersTest.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/TestResourcesPropertyProvidersTest.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/test/resources/application-test.yml create mode 100644 test-resources-extensions/test-resources-extensions-core/src/test/resources/logback.xml create mode 100644 test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/FakeTestResourcesClient.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/FakeTestResourcesClientInjector.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/SomeBean.java create mode 100644 test-resources-extensions/test-resources-extensions-core/src/testFixtures/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener diff --git a/buildSrc/src/main/groovy/io.micronaut.build.internal.test-resources-mntest-extension.gradle b/buildSrc/src/main/groovy/io.micronaut.build.internal.test-resources-mntest-extension.gradle new file mode 100644 index 000000000..204d473e3 --- /dev/null +++ b/buildSrc/src/main/groovy/io.micronaut.build.internal.test-resources-mntest-extension.gradle @@ -0,0 +1,12 @@ +plugins { + id 'io.micronaut.build.internal.test-resources-simple-module' + id 'io.micronaut.build.internal.test-fixtures' +} + +components.java.withVariantsFromConfiguration(configurations.testFixturesApiElements) { skip() } +components.java.withVariantsFromConfiguration(configurations.testFixturesRuntimeElements) { skip() } + +micronautBuild { + def (String major, String minor, String patch) = (version - '-SNAPSHOT').split("[.]") + binaryCompatibility.enabled = major.toInteger() >=2 && minor.toInteger() >= 0 && patch.toInteger() > 0 +} diff --git a/buildSrc/src/main/groovy/io.micronaut.build.internal.test-resources-simple-module.gradle b/buildSrc/src/main/groovy/io.micronaut.build.internal.test-resources-simple-module.gradle new file mode 100644 index 000000000..0323f7bdf --- /dev/null +++ b/buildSrc/src/main/groovy/io.micronaut.build.internal.test-resources-simple-module.gradle @@ -0,0 +1,9 @@ +/** + * Use this plugin for modules which are not Micronaut modules + * but follow the same conventions (e.g need publishing, binary + * compatibilty, etc...) + */ +plugins { + id 'io.micronaut.build.internal.test-resources-base' + id 'io.micronaut.build.internal.base-module' +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 73d86ec12..0137e60dc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,7 +36,7 @@ micronaut-redis = "6.0.0-M2" micronaut-security = "4.0.0-M2" micronaut-serde = "2.0.0-M3" micronaut-sql = "5.0.0-M3" -micronaut-test = "4.0.0-M2" +micronaut-test = "4.0.0-M3" micronaut-gradle-plugin = "4.0.0-M1" groovy = "4.0.11" spock = "2.3-groovy-4.0" @@ -51,6 +51,10 @@ managed-testcontainers = "1.17.6" [libraries] boms-testcontainers = { module = "org.testcontainers:testcontainers-bom", version.ref = "managed-testcontainers" } +junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api" } +junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine" } +junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher"} + micronaut-aws = { module = "io.micronaut.aws:micronaut-aws-bom", version.ref = "micronaut-aws" } micronaut-data = { module = "io.micronaut.data:micronaut-data-bom", version.ref = "micronaut-data" } micronaut-discovery = { module = "io.micronaut.discovery:micronaut-discovery-client", version.ref = "micronaut-discovery" } diff --git a/settings.gradle b/settings.gradle index 3c6f4c43e..1add53c4c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,16 @@ plugins { } rootProject.name = 'testresources-parent' +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + +// Extensions as in "Micronaut Test extensions" +// This name was chosen to reduce the naming overhead +// e.g micronaut-test-resources-micronaut-test-extensions-core +// is just micronaut-test-resources-extensions-core +def extensionModules = [ + 'core' +] + def jdbcModules = [ 'core', 'mysql', @@ -52,6 +62,7 @@ include 'test-resources-client' include 'test-resources-elasticsearch' include 'test-resources-embedded' include 'test-resources-hivemq' +include 'test-resources-junit5' include 'test-resources-kafka' include 'test-resources-mongodb' include 'test-resources-neo4j' @@ -61,6 +72,11 @@ include 'test-resources-server' include 'test-resources-testcontainers' include 'test-resources-hashicorp-vault' +extensionModules.each { + String projectName = "test-resources-extensions-$it" + include projectName + project(":test-resources-extensions-$it").projectDir = file("test-resources-extensions/$projectName") +} jdbcModules.each { String projectName = "test-resources-jdbc-$it" include projectName diff --git a/test-resources-extensions/test-resources-extensions-core/build.gradle b/test-resources-extensions/test-resources-extensions-core/build.gradle new file mode 100644 index 000000000..f17e6c62c --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'io.micronaut.build.internal.test-resources-mntest-extension' +} + +description = """ +Provides Micronaut Test extensions which make it easier to integrate +with Test Resources. +""" + +dependencies { + // Sync'es the version of JUnit 5 used by Micronaut Test + api(platform(mnTest.micronaut.test.bom)) + api(mnTest.micronaut.test.core) + implementation(projects.micronautTestResourcesClient) + + testAnnotationProcessor(mn.micronaut.inject.java) + testImplementation(mnTest.micronaut.test.junit5) + testFixturesAnnotationProcessor(mn.micronaut.inject.java) + testFixturesApi(libs.junit.platform.launcher) + testFixturesApi(platform(mnTest.micronaut.test.bom)) + testFixturesImplementation(projects.micronautTestResourcesClient) + testRuntimeOnly(libs.junit.jupiter.engine) + testRuntimeOnly(mn.micronaut.context) + testRuntimeOnly(mn.snakeyaml) +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesClientHolder.java b/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesClientHolder.java new file mode 100644 index 000000000..eee49834d --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesClientHolder.java @@ -0,0 +1,96 @@ +/* + * Copyright 2017-2021 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import io.micronaut.core.annotation.Internal; +import io.micronaut.testresources.client.TestResourcesClient; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; + +/** + * An internal class which can be used to inject a fake + * test resources client, for testing purposes. + */ +@Internal +public final class TestResourcesClientHolder { + private static TestResourcesClient CLIENT; + + private TestResourcesClientHolder() { + + } + + public static void set(TestResourcesClient client) { + CLIENT = client; + } + + public static TestResourcesClient get() { + return CLIENT; + } + + public static TestResourcesClient lazy() { + return new LazyTestResourcesClient(); + } + + private static class LazyTestResourcesClient implements TestResourcesClient { + + private static T nullSafe(Supplier value) { + if (CLIENT == null) { + return null; + } + return value.get(); + } + + @Override + public List getResolvableProperties(Map> propertyEntries, Map testResourcesConfig) { + return nullSafe(CLIENT::getResolvableProperties); + } + + @Override + public Optional resolve(String name, Map properties, Map testResourcesConfiguration) { + return nullSafe(() -> CLIENT.resolve(name, properties, testResourcesConfiguration)); + } + + @Override + public List getRequiredProperties(String expression) { + return nullSafe(() -> CLIENT.getRequiredProperties(expression)); + } + + @Override + public List getRequiredPropertyEntries() { + return nullSafe(CLIENT::getRequiredPropertyEntries); + } + + @Override + public boolean closeAll() { + return nullSafe(CLIENT::closeAll); + } + + @Override + public boolean closeScope(String id) { + return nullSafe(() -> CLIENT.closeScope(id)); + } + + @Override + public List getResolvableProperties() { + return nullSafe(CLIENT::getResolvableProperties); + } + + } +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesPropertiesFactory.java b/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesPropertiesFactory.java new file mode 100644 index 000000000..81b389dfe --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesPropertiesFactory.java @@ -0,0 +1,94 @@ +/* + * Copyright 2017-2021 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import io.micronaut.test.extensions.testresources.annotation.TestResourcesProperties; +import io.micronaut.test.support.TestPropertyProvider; +import io.micronaut.test.support.TestPropertyProviderFactory; +import io.micronaut.testresources.client.TestResourcesClientFactory; + +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class TestResourcesPropertiesFactory implements TestPropertyProviderFactory { + @Override + public TestPropertyProvider create(Map properties, Class testClass) { + return new TestResourcesTestPropertyProvider(testClass, properties); + + } + + private static TestResourcesPropertyProvider instantitateProvider(Class provider) { + try { + return provider.getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + throw new RuntimeException("Test resources property provider must have a public constructor without arguments", e); + } + } + + private static class TestResourcesTestPropertyProvider implements TestPropertyProvider { + public static final String TEST_RESOURCES_PROPERTY_PREFIX = "test-resources."; + private final Class testClass; + private final Map properties; + + public TestResourcesTestPropertyProvider(Class testClass, Map properties) { + this.testClass = testClass; + this.properties = properties; + } + + @Override + public Map getProperties() { + TestResourcesProperties annotation = testClass.getAnnotation(TestResourcesProperties.class); + if (annotation != null) { + String[] requestedProperties = annotation.value(); + var client = TestResourcesClientFactory.fromSystemProperties() + .orElse(TestResourcesClientHolder.lazy()); + var testResourcesConfig = properties.entrySet() + .stream() + .filter(e -> e.getKey().startsWith(TEST_RESOURCES_PROPERTY_PREFIX)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + Map resolvedProperties = Stream.of(requestedProperties) + .map(v -> new Object() { + private final String key = v; + private final String value = client.resolve(v, Map.of(), testResourcesConfig).orElse(null); + }) + .filter(o -> o.value != null) + .collect(Collectors.toMap(e -> e.key, e -> e.value)); + + // Result represents what properties we're going to expose to tests + Map result = new HashMap<>(resolvedProperties); + // Context represents what is available to resolvers for them to + // compute results + Map context = new HashMap<>(properties); + context.putAll(resolvedProperties); + result.putAll(resolvedProperties); + Class[] providers = annotation.providers(); + for (Class provider : providers) { + var testResourcesPropertyProvider = instantitateProvider(provider); + Map map = testResourcesPropertyProvider.provide(Collections.unmodifiableMap(context)); + context.putAll(map); + result.putAll(map); + } + return result; + } + return Map.of(); + } + } +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesPropertyProvider.java b/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesPropertyProvider.java new file mode 100644 index 000000000..daa064a03 --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/TestResourcesPropertyProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright 2017-2021 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import io.micronaut.core.annotation.NonNull; + +import java.util.Map; + +/** + * A test resources property provider is a type which + * must be explicitly declared in via the {@link io.micronaut.test.extensions.testresources.annotation.TestResourcesProperties} + * annotation. + *

+ * It is responsible for supplying additional test properties, + * given the set of properties which are available before the + * application context is started. + *

+ * It can be used, in particular, to derive new properties + * from other properties resolved by the test resources client. + *

+ * This works in a very similar way as {@link io.micronaut.test.support.TestPropertyProvider}, + * but has access to other properties in order to perform + * computation based on the value of these properties. + */ +@FunctionalInterface +public interface TestResourcesPropertyProvider { + /** + * Returns a map of properties which need to be exposed + * to the application context, given the map of properties + * which are already available during setup. + * + * These properties typically include the properties + * visible in the configuration files which do not require + * access to test resources. + * + * @param testProperties the set of properties available + * @return a map of properties to be added + */ + @NonNull + Map provide(@NonNull Map testProperties); +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/annotation/TestResourcesProperties.java b/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/annotation/TestResourcesProperties.java new file mode 100644 index 000000000..5ac6ba0fb --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/main/java/io/micronaut/test/extensions/testresources/annotation/TestResourcesProperties.java @@ -0,0 +1,55 @@ +/* + * Copyright 2017-2021 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources.annotation; + +import io.micronaut.test.extensions.testresources.TestResourcesPropertyProvider; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation can be applied to tests annotated with {@literal @MicronautTest} + * in order to require some properties to be resolved by Micronaut Test Resources + * before the application context is available. + *

+ * It is conceptually similar to a {@link io.micronaut.test.support.TestPropertyProvider} + * except that it allows accessing the test resources properties declaratively + * instead of having to use the test resources client directly. + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE}) +public @interface TestResourcesProperties { + /** + * Declares the list of properties which should be made available + * to the test before the application context is started. + * These properties will be queried by the test resources client + * and exposed as properties to the test. + * + * @return the list of properties + */ + String[] value() default {}; + + /** + * The optional list of test resource property providers which + * can be applied to enhance the set of properties available to + * a test. + * @return the list of providers + */ + Class[] providers() default {}; +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/main/resources/META-INF/services/io.micronaut.test.support.TestPropertyProviderFactory b/test-resources-extensions/test-resources-extensions-core/src/main/resources/META-INF/services/io.micronaut.test.support.TestPropertyProviderFactory new file mode 100644 index 000000000..b252aea7e --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/main/resources/META-INF/services/io.micronaut.test.support.TestPropertyProviderFactory @@ -0,0 +1 @@ +io.micronaut.test.extensions.testresources.TestResourcesPropertiesFactory diff --git a/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/ConfigurationFilesTestResourcesPropertyProvidersTest.java b/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/ConfigurationFilesTestResourcesPropertyProvidersTest.java new file mode 100644 index 000000000..efcc56a82 --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/ConfigurationFilesTestResourcesPropertyProvidersTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2003-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import io.micronaut.context.annotation.Value; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import io.micronaut.test.extensions.testresources.annotation.TestResourcesProperties; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@MicronautTest +@TestResourcesProperties( + providers = ConfigurationFilesTestResourcesPropertyProvidersTest.MyProvider.class +) +public class ConfigurationFilesTestResourcesPropertyProvidersTest { + + @Value("${derived.toto}") + Integer value; + + @Value("${test-resources-config-visible}") + Boolean testResourcesConfigurationIsVisible; + + @Test + @DisplayName("configuration properties are accessible to the provider") + public void canCallTestResourcesClient() { + assertEquals(42, value); + assertEquals(Boolean.TRUE, testResourcesConfigurationIsVisible); + } + + public static class MyProvider implements TestResourcesPropertyProvider { + @Override + public Map provide(Map testProperties) { + return Map.of( + "derived.toto", String.valueOf(2 + (Integer) testProperties.get("toto")), + "test-resources-config-visible", String.valueOf(testProperties.containsKey("test-resources.containers.nats.image-name")) + ); + } + } +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/SimpleTestResourcesPropertyProvidersTest.java b/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/SimpleTestResourcesPropertyProvidersTest.java new file mode 100644 index 000000000..ba892a48b --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/SimpleTestResourcesPropertyProvidersTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2003-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import io.micronaut.context.annotation.Value; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import io.micronaut.test.extensions.testresources.annotation.TestResourcesProperties; +import jakarta.inject.Inject; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@MicronautTest +@TestResourcesProperties( + value = {"first-property", "second-property"} +) +public class SimpleTestResourcesPropertyProvidersTest { + + @Value("${first-property}") + String first; + + @Inject + SomeBean someBean; + + @Test + @DisplayName("properties can be computed from test resources") + public void canCallTestResourcesClient() { + assertEquals("first supplied by test resources", first); + assertEquals("second supplied by test resources", someBean.getSomeValue()); + } + +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/TestResourcesPropertyProvidersTest.java b/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/TestResourcesPropertyProvidersTest.java new file mode 100644 index 000000000..a259642c5 --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/test/java/io/micronaut/test/extensions/testresources/TestResourcesPropertyProvidersTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2003-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import io.micronaut.context.annotation.Value; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import io.micronaut.test.extensions.testresources.annotation.TestResourcesProperties; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@MicronautTest +@TestResourcesProperties( + value = "some-property", + providers = TestResourcesPropertyProvidersTest.MyProvider.class +) +public class TestResourcesPropertyProvidersTest { + + @Value("${some-other-property}") + String derivedFromTestResources; + + @Test + @DisplayName("properties can be computed from test resources") + public void canDerivePropertiesFromTestResources() { + assertEquals("supplied by test resources and transformed", derivedFromTestResources); + } + + public static class MyProvider implements TestResourcesPropertyProvider { + @Override + public Map provide(Map testProperties) { + String str = (String) testProperties.get("some-property"); + return Map.of( + "some-other-property", str + " and transformed" + ); + } + } + +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/test/resources/application-test.yml b/test-resources-extensions/test-resources-extensions-core/src/test/resources/application-test.yml new file mode 100644 index 000000000..10bfe6c0f --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/test/resources/application-test.yml @@ -0,0 +1,12 @@ +test-resources: + containers: + nats: + startup-timeout: 600s + image-name: nats:latest + exposed-ports: + - nats.port: 4222 + command: "--js" + wait-strategy: + log: + regex: ".*Server is ready.*" +toto: 40 diff --git a/test-resources-extensions/test-resources-extensions-core/src/test/resources/logback.xml b/test-resources-extensions/test-resources-extensions-core/src/test/resources/logback.xml new file mode 100644 index 000000000..44b79c40d --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/test/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/FakeTestResourcesClient.java b/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/FakeTestResourcesClient.java new file mode 100644 index 000000000..d4f7a6a67 --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/FakeTestResourcesClient.java @@ -0,0 +1,61 @@ +/* + * Copyright 2003-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import io.micronaut.testresources.client.TestResourcesClient; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class FakeTestResourcesClient implements TestResourcesClient { + private static final Map MOCK_PROPERTIES = Map.of( + "first-property", "first supplied by test resources", + "second-property", "second supplied by test resources", + "some-property", "supplied by test resources" + ); + + @Override + public List getResolvableProperties(Map> propertyEntries, Map testResourcesConfig) { + return MOCK_PROPERTIES.keySet().stream().toList(); + } + + @Override + public Optional resolve(String name, Map properties, Map testResourcesConfiguration) { + return Optional.ofNullable(MOCK_PROPERTIES.get(name)); + } + + @Override + public List getRequiredProperties(String expression) { + return List.of(); + } + + @Override + public List getRequiredPropertyEntries() { + return List.of(); + } + + @Override + public boolean closeAll() { + return true; + } + + @Override + public boolean closeScope(String id) { + return true; + } +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/FakeTestResourcesClientInjector.java b/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/FakeTestResourcesClientInjector.java new file mode 100644 index 000000000..16611428c --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/FakeTestResourcesClientInjector.java @@ -0,0 +1,31 @@ +/* + * Copyright 2003-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestPlan; + +public class FakeTestResourcesClientInjector implements TestExecutionListener { + @Override + public void testPlanExecutionStarted(TestPlan testPlan) { + TestResourcesClientHolder.set(new FakeTestResourcesClient()); + } + + @Override + public void testPlanExecutionFinished(TestPlan testPlan) { + TestResourcesClientHolder.set(null); + } +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/SomeBean.java b/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/SomeBean.java new file mode 100644 index 000000000..3e1bf2cdc --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/testFixtures/java/io/micronaut/test/extensions/testresources/SomeBean.java @@ -0,0 +1,32 @@ +/* + * Copyright 2003-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.test.extensions.testresources; + +import io.micronaut.context.annotation.Value; +import jakarta.inject.Singleton; + +@Singleton +public class SomeBean { + private final String someValue; + + public SomeBean(@Value("${second-property}") String someValue) { + this.someValue = someValue; + } + + public String getSomeValue() { + return someValue; + } +} diff --git a/test-resources-extensions/test-resources-extensions-core/src/testFixtures/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener b/test-resources-extensions/test-resources-extensions-core/src/testFixtures/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener new file mode 100644 index 000000000..843cd2229 --- /dev/null +++ b/test-resources-extensions/test-resources-extensions-core/src/testFixtures/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener @@ -0,0 +1 @@ +io.micronaut.test.extensions.testresources.FakeTestResourcesClientInjector