From 26566d4a30233bb002449a2c0d7a8ffc84d3438e Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 2 May 2023 18:55:03 -0700 Subject: [PATCH] Allow testcontainer beans to also contribute properties Allow `Container` bean definitions to inject a `DynamicPropertyRegistry` so that they can contribute environment properties. Closes gh-35201 --- .../spring-boot-docs/build.gradle | 1 + .../src/docs/asciidoc/features/testing.adoc | 15 +++ .../MyContainersConfiguration.java | 36 ++++++ .../MyContainersConfiguration.kt | 35 ++++++ .../spring-boot-testcontainers/build.gradle | 1 + .../TestcontainersPropertySource.java | 93 ++++++++++++++++ ...ainersPropertySourceAutoConfiguration.java | 42 +++++++ .../properties/package-info.java | 20 ++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + ...sPropertySourceAutoConfigurationTests.java | 86 +++++++++++++++ .../TestcontainersPropertySourceTests.java | 104 ++++++++++++++++++ ...opertiesSampleSessionRedisApplication.java | 44 ++++++++ ...nectionSampleSessionRedisApplication.java} | 24 ++-- 13 files changed, 491 insertions(+), 11 deletions(-) create mode 100644 spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/testcontainers/atdevelopmenttime/dynamicproperties/MyContainersConfiguration.java create mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/features/testing/testcontainers/atdevelopmenttime/dynamicproperties/MyContainersConfiguration.kt create mode 100644 spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceAutoConfiguration.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/package-info.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceAutoConfigurationTests.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceTests.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestPropertiesSampleSessionRedisApplication.java rename spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/{TestSampleSessionRedisApplication.java => TestServiceConnectionSampleSessionRedisApplication.java} (73%) diff --git a/spring-boot-project/spring-boot-docs/build.gradle b/spring-boot-project/spring-boot-docs/build.gradle index 3dc42b8eef..b2eac745a2 100644 --- a/spring-boot-project/spring-boot-docs/build.gradle +++ b/spring-boot-project/spring-boot-docs/build.gradle @@ -163,6 +163,7 @@ dependencies { implementation("org.springframework.ws:spring-ws-test") implementation("org.testcontainers:junit-jupiter") implementation("org.testcontainers:neo4j") + implementation("org.testcontainers:mongodb") implementation("org.junit.jupiter:junit-jupiter") implementation("org.yaml:snakeyaml") diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc index 2dc2e24127..e9f65a1752 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc @@ -1047,6 +1047,21 @@ You can now launch `TestMyApplication` as you would any regular Java `main` meth + +[[features.testing.testcontainers.at-development-time.dynamic-properties]] +===== Contributing Dynamic Properties at Development Time +If you want to contribute dynamic properties at development time from your `Container` `@Bean` methods, you can do so by injecting a `DynamicPropertyRegistry`. +This works in a similar way to the <> that you can use in your tests. +It allows you to add properties that will become available once your container has started. + +A typical configuration would look like this: + +include::code:MyContainersConfiguration[] + +NOTE: Using a `@ServiceConnection` is recommended whenever possible, however, dynamic properties can be a useful fallback for technologies that don't yet have `@ServiceConnection` support. + + + [[features.testing.utilities]] === Test Utilities A few test utility classes that are generally useful when testing your application are packaged as part of `spring-boot`. diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/testcontainers/atdevelopmenttime/dynamicproperties/MyContainersConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/testcontainers/atdevelopmenttime/dynamicproperties/MyContainersConfiguration.java new file mode 100644 index 0000000000..a1d4bcc714 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/features/testing/testcontainers/atdevelopmenttime/dynamicproperties/MyContainersConfiguration.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012-2023 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 org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.dynamicproperties; + +import org.testcontainers.containers.MongoDBContainer; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; + +@TestConfiguration(proxyBeanMethods = false) +public class MyContainersConfiguration { + + @Bean + public MongoDBContainer monogDbContainer(DynamicPropertyRegistry properties) { + MongoDBContainer container = new MongoDBContainer("mongo:5.0"); + properties.add("spring.data.mongodb.host", container::getHost); + properties.add("spring.data.mongodb.port", container::getFirstMappedPort); + return container; + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/features/testing/testcontainers/atdevelopmenttime/dynamicproperties/MyContainersConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/features/testing/testcontainers/atdevelopmenttime/dynamicproperties/MyContainersConfiguration.kt new file mode 100644 index 0000000000..c992efeaf9 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/features/testing/testcontainers/atdevelopmenttime/dynamicproperties/MyContainersConfiguration.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2023 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 org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.dynamicproperties + +import org.springframework.boot.test.context.TestConfiguration +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry +import org.testcontainers.containers.MongoDBContainer + +@TestConfiguration(proxyBeanMethods = false) +class MyContainersConfiguration { + + @Bean + fun monogDbContainer(properties: DynamicPropertyRegistry): MongoDBContainer { + var container = MongoDBContainer("mongo:5.0") + properties.add("spring.data.mongodb.host", container::getHost); + properties.add("spring.data.mongodb.port", container::getFirstMappedPort); + return container + } + +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-testcontainers/build.gradle b/spring-boot-project/spring-boot-testcontainers/build.gradle index 6942ac93e7..0e6c1754c3 100644 --- a/spring-boot-project/spring-boot-testcontainers/build.gradle +++ b/spring-boot-project/spring-boot-testcontainers/build.gradle @@ -33,6 +33,7 @@ dependencies { optional("org.testcontainers:r2dbc") testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) + testImplementation(project(":spring-boot-project:spring-boot-test")) testImplementation("ch.qos.logback:logback-classic") testImplementation("org.assertj:assertj-core") testImplementation("org.awaitility:awaitility") diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java new file mode 100644 index 0000000000..03cc093229 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySource.java @@ -0,0 +1,93 @@ +/* + * Copyright 2012-2023 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 org.springframework.boot.testcontainers.properties; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +import org.testcontainers.containers.Container; + +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertySource; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * {@link EnumerablePropertySource} backed by a map with values supplied from one or more + * {@link Container testcontainers}. + * + * @author Phillip Webb + * @since 3.1.0 + */ +public class TestcontainersPropertySource extends EnumerablePropertySource>> { + + static final String NAME = "testcontainersPropertySource"; + + private final DynamicPropertyRegistry registry; + + TestcontainersPropertySource() { + this(Collections.synchronizedMap(new LinkedHashMap<>())); + } + + private TestcontainersPropertySource(Map> valueSuppliers) { + super(NAME, Collections.unmodifiableMap(valueSuppliers)); + this.registry = (name, valueSupplier) -> { + Assert.hasText(name, "'name' must not be null or blank"); + Assert.notNull(valueSupplier, "'valueSupplier' must not be null"); + valueSuppliers.put(name, valueSupplier); + }; + } + + @Override + public Object getProperty(String name) { + Supplier valueSupplier = this.source.get(name); + return (valueSupplier != null) ? valueSupplier.get() : null; + } + + @Override + public boolean containsProperty(String name) { + return this.source.containsKey(name); + } + + @Override + public String[] getPropertyNames() { + return StringUtils.toStringArray(this.source.keySet()); + } + + public static DynamicPropertyRegistry attach(Environment environment) { + Assert.state(environment instanceof ConfigurableEnvironment, + "TestcontainersPropertySource can only be attached to a ConfigurableEnvironment"); + return attach((ConfigurableEnvironment) environment); + } + + private static DynamicPropertyRegistry attach(ConfigurableEnvironment environment) { + PropertySource propertySource = environment.getPropertySources().get(NAME); + if (propertySource == null) { + environment.getPropertySources().addFirst(new TestcontainersPropertySource()); + return attach(environment); + } + Assert.state(propertySource instanceof TestcontainersPropertySource, + "Incorrect DynamicValuesPropertySource type registered"); + return ((TestcontainersPropertySource) propertySource).registry; + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceAutoConfiguration.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceAutoConfiguration.java new file mode 100644 index 0000000000..5c016c964e --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceAutoConfiguration.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2023 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 org.springframework.boot.testcontainers.properties; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.test.context.DynamicPropertyRegistry; + +/** + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} to add {@link TestcontainersPropertySource} support. + * + * @author Phillip Webb + * @since 3.1.0 + */ +@ConditionalOnClass(DynamicPropertyRegistry.class) +public class TestcontainersPropertySourceAutoConfiguration { + + TestcontainersPropertySourceAutoConfiguration() { + } + + @Bean + DynamicPropertyRegistry dynamicPropertyRegistry(ConfigurableEnvironment environment) { + return TestcontainersPropertySource.attach(environment); + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/package-info.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/package-info.java new file mode 100644 index 0000000000..2662b46978 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/properties/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2023 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. + */ + +/** + * Dynamic container properties support. + */ +package org.springframework.boot.testcontainers.properties; diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 841426d00c..3e0cefae44 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ +org.springframework.boot.testcontainers.properties.DynamicProperySourceAutoConfiguration org.springframework.boot.testcontainers.service.connection.ServiceConnectionAutoConfiguration diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceAutoConfigurationTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceAutoConfigurationTests.java new file mode 100644 index 0000000000..583640f2e8 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceAutoConfigurationTests.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012-2023 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 org.springframework.boot.testcontainers.properties; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleApplicationContextInitializer; +import org.springframework.boot.testsupport.testcontainers.RedisContainer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.DynamicPropertyRegistry; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link TestcontainersPropertySourceAutoConfiguration}. + * + * @author Phillip Webb + */ +class TestcontainersPropertySourceAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withInitializer(new TestcontainersLifecycleApplicationContextInitializer()) + .withConfiguration(AutoConfigurations.of(TestcontainersPropertySourceAutoConfiguration.class)); + + @Test + void containerBeanMethodContributesProperties() { + this.contextRunner.withUserConfiguration(ContainerAndPropertiesConfiguration.class).run((context) -> { + TestBean testBean = context.getBean(TestBean.class); + RedisContainer redisContainer = context.getBean(RedisContainer.class); + assertThat(testBean.getUsingPort()).isEqualTo(redisContainer.getFirstMappedPort()); + }); + } + + @Configuration(proxyBeanMethods = false) + @EnableConfigurationProperties(ContainerProperties.class) + @Import(TestBean.class) + static class ContainerAndPropertiesConfiguration { + + @Bean + RedisContainer redisContainer(DynamicPropertyRegistry properties) { + RedisContainer container = new RedisContainer(); + properties.add("container.port", container::getFirstMappedPort); + return container; + } + + } + + @ConfigurationProperties("container") + static record ContainerProperties(int port) { + } + + static class TestBean { + + private int usingPort; + + TestBean(ContainerProperties containerProperties) { + this.usingPort = containerProperties.port(); + } + + int getUsingPort() { + return this.usingPort; + } + + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceTests.java new file mode 100644 index 0000000000..7958666992 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/properties/TestcontainersPropertySourceTests.java @@ -0,0 +1,104 @@ +/* + * Copyright 2012-2023 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 org.springframework.boot.testcontainers.properties; + +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.mock.env.MockEnvironment; +import org.springframework.test.context.DynamicPropertyRegistry; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +/** + * Tests for {@link TestcontainersPropertySource}. + * + * @author Phillip Webb + */ +class TestcontainersPropertySourceTests { + + private MockEnvironment environment = new MockEnvironment(); + + @Test + void getPropertyWhenHasValueSupplierReturnsSuppliedValue() { + DynamicPropertyRegistry registry = TestcontainersPropertySource.attach(this.environment); + registry.add("test", () -> "spring"); + assertThat(this.environment.getProperty("test")).isEqualTo("spring"); + } + + @Test + void getPropertyWhenHasNoValueSupplierReturnsNull() { + DynamicPropertyRegistry registry = TestcontainersPropertySource.attach(this.environment); + registry.add("test", () -> "spring"); + assertThat(this.environment.getProperty("missing")).isNull(); + } + + @Test + void containsPropertyWhenHasPropertyReturnsTrue() { + DynamicPropertyRegistry registry = TestcontainersPropertySource.attach(this.environment); + registry.add("test", () -> null); + assertThat(this.environment.containsProperty("test")).isTrue(); + } + + @Test + void containsPropertyWhenHasNoPropertyReturnsFalse() { + DynamicPropertyRegistry registry = TestcontainersPropertySource.attach(this.environment); + registry.add("test", () -> null); + assertThat(this.environment.containsProperty("missing")).isFalse(); + } + + @Test + void getPropertyNamesReturnsNames() { + DynamicPropertyRegistry registry = TestcontainersPropertySource.attach(this.environment); + registry.add("test", () -> null); + registry.add("other", () -> null); + EnumerablePropertySource propertySource = (EnumerablePropertySource) this.environment.getPropertySources() + .get(TestcontainersPropertySource.NAME); + assertThat(propertySource.getPropertyNames()).containsExactly("test", "other"); + } + + @Test + @SuppressWarnings("unchecked") + void getSourceReturnsImmutableSource() { + TestcontainersPropertySource.attach(this.environment); + PropertySource propertySource = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); + Map map = (Map) propertySource.getSource(); + assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(map::clear); + } + + @Test + void attachWhenNotAttachedAttaches() { + TestcontainersPropertySource.attach(this.environment); + PropertySource propertySource = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); + assertThat(propertySource).isNotNull(); + } + + @Test + void attachWhenAlreadyAttachedReturnsExisting() { + DynamicPropertyRegistry r1 = TestcontainersPropertySource.attach(this.environment); + PropertySource p1 = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); + DynamicPropertyRegistry r2 = TestcontainersPropertySource.attach(this.environment); + PropertySource p2 = this.environment.getPropertySources().get(TestcontainersPropertySource.NAME); + assertThat(r1).isSameAs(r2); + assertThat(p1).isSameAs(p2); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestPropertiesSampleSessionRedisApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestPropertiesSampleSessionRedisApplication.java new file mode 100644 index 0000000000..f2a510f737 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestPropertiesSampleSessionRedisApplication.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012-2023 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 smoketest.session.redis; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testsupport.testcontainers.RedisContainer; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; + +public class TestPropertiesSampleSessionRedisApplication { + + public static void main(String[] args) { + SpringApplication.from(SampleSessionRedisApplication::main).with(ContainerConfiguration.class).run(args); + } + + @TestConfiguration(proxyBeanMethods = false) + static class ContainerConfiguration { + + @Bean + RedisContainer redisContainer(DynamicPropertyRegistry properties) { + RedisContainer container = new RedisContainer(); + properties.add("spring.data.redis.host", container::getHost); + properties.add("spring.data.redis.port", container::getFirstMappedPort); + return container; + } + + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestSampleSessionRedisApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestServiceConnectionSampleSessionRedisApplication.java similarity index 73% rename from spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestSampleSessionRedisApplication.java rename to spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestServiceConnectionSampleSessionRedisApplication.java index 6c65ec610e..ef7ddb3903 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestSampleSessionRedisApplication.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-redis/src/test/java/smoketest/session/redis/TestServiceConnectionSampleSessionRedisApplication.java @@ -22,19 +22,21 @@ import org.springframework.boot.testcontainers.service.connection.ServiceConnect import org.springframework.boot.testsupport.testcontainers.RedisContainer; import org.springframework.context.annotation.Bean; -@TestConfiguration(proxyBeanMethods = false) -public class TestSampleSessionRedisApplication { - - @Bean - @ServiceConnection("redis") - RedisContainer redisContainer() { - return new RedisContainer(); - } +public class TestServiceConnectionSampleSessionRedisApplication { public static void main(String[] args) { - SpringApplication.from(SampleSessionRedisApplication::main) - .with(TestSampleSessionRedisApplication.class) - .run(args); + SpringApplication.from(SampleSessionRedisApplication::main).with(ContainerConfiguration.class).run(args); + } + + @TestConfiguration(proxyBeanMethods = false) + static class ContainerConfiguration { + + @Bean + @ServiceConnection("redis") + RedisContainer redisContainer() { + return new RedisContainer(); + } + } }