From 4a98b1787f18507d837eaeae7bd7e38bc05fabd7 Mon Sep 17 00:00:00 2001 From: Vanio Begic Date: Sun, 9 Feb 2025 09:28:41 +0100 Subject: [PATCH 1/2] Document methods of starting Testcontainer containers Update the reference documentation to provide more details about the three supported methods of starting Testcontainer containers. See gh-44187 Signed-off-by: Vanio Begic --- .../antora-asciidoc-attributes.properties | 1 + .../pages/testing/testcontainers.adoc | 78 ++++++++++++++++++- .../BeanDeclarationConfig.java | 35 +++++++++ .../beandeclaration/SpringTest.java | 38 +++++++++ .../importcontainers/MyConfiguration.java | 26 +++++++ .../importcontainers/MyInterface.java | 35 +++++++++ .../beandeclaration/BeanDeclarationConfig.kt | 17 ++++ .../beandeclaration/SpringTest.kt | 19 +++++ src/checkstyle/checkstyle-suppressions.xml | 1 + 9 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.java create mode 100644 spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.java create mode 100644 spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyConfiguration.java create mode 100644 spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyInterface.java create mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.kt create mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.kt diff --git a/buildSrc/src/main/resources/org/springframework/boot/build/antora/antora-asciidoc-attributes.properties b/buildSrc/src/main/resources/org/springframework/boot/build/antora/antora-asciidoc-attributes.properties index 0183ad7e7c1..e2098cbe411 100644 --- a/buildSrc/src/main/resources/org/springframework/boot/build/antora/antora-asciidoc-attributes.properties +++ b/buildSrc/src/main/resources/org/springframework/boot/build/antora/antora-asciidoc-attributes.properties @@ -75,6 +75,7 @@ url-spring-data-rest-docs=https://docs.spring.io/spring-data/rest/reference/{ant url-spring-data-rest-site=https://spring.io/projects/spring-data-rest url-spring-data-rest-javadoc=https://docs.spring.io/spring-data/rest/docs/{dotxversion-spring-data-rest}/api url-spring-data-site=https://spring.io/projects/spring-data +url-testcontainers-java-doc=https://java.testcontainers.org url-testcontainers-activemq-javadoc=https://javadoc.io/doc/org.testcontainers/activemq/{version-testcontainers-activemq} url-testcontainers-cassandra-javadoc=https://javadoc.io/doc/org.testcontainers/cassandra/{version-testcontainers-cassandra} url-testcontainers-couchbase-javadoc=https://javadoc.io/doc/org.testcontainers/couchbase/{version-testcontainers-couchbase} diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc index 853ee2b28dc..5325e6a85dd 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc @@ -5,13 +5,89 @@ The https://www.testcontainers.org/[Testcontainers] library provides a way to ma It integrates with JUnit, allowing you to write a test class that can start up a container before any of the tests run. Testcontainers is especially useful for writing integration tests that talk to a real backend service such as MySQL, MongoDB, Cassandra and others. +In following sections we will describe some of the methods you can use to integrate Testcontainers with your tests. + + + +[[testing.testcontainers.via-junit-extension]] +== Using via @Testcontainers JUnit5 extension + +The Testcontainers provides JUnit5 extensions, which can be used to manage containers in your tests. +The extension is activated by applying the `@Testcontainers` annotation from Testcontainers to your test class. + Testcontainers can be used in a Spring Boot test as follows: include-code::vanilla/MyIntegrationTests[] -This will start up a docker container running Neo4j (if Docker is running locally) before any of the tests are run. +This will start up a Docker container running Neo4j (if Docker is running locally) before any of the tests are run. In most cases, you will need to configure the application to connect to the service running in the container. +In this case the lifecycle of the container instance is managed by Testcontainers, as described in official documentation. + + +[[testing.testcontainers.via-spring-beans]] +== Using via Spring managed beans + +The containers provided by Testcontainers can be managed by Spring Boot as beans. +This method of managing contains can be used in combination with javadoc:org.springframework.boot.testcontainers.service.connection.ServiceConnection[format=annotation]. + +To use Testcontainer contains as Spring beans we need to create a configuration class declaring the container as bean: + +include-code::beandeclaration/BeanDeclarationConfig[] + +then we can start the container by importing the configuration class in the test class: + +include-code::beandeclaration/SpringTest[] + + +[[testing.testcontainers.via-declaration-classes]] +== Using via importing container declaration classes + +A common pattern with Testcontainers is to declare the Container instances as static fields in an interface. +For example the following interface `MyInterface` declares two containers, one named `mongo` of type MongoDB and another named `neo` of type Neo4j: + +include-code::importcontainers/MyInterface[] + +When you have containers declared in this way, then you can have these containers managed by Spring Boot as beans. +All that is needed to do that is adding javadoc:org.springframework.boot.testcontainers.context.ImportTestcontainers[format=annotation] to your configuration class as in: + +include-code::importcontainers/MyConfiguration[] + +TIP: Using interfaces for declaring contains helps with reuse. +When containers are declared in an interface, this can be reused in your javadoc:org.springframework.context.annotation.Configuration[format=annotation] classes and in test classes. + + +[[test.testcontainers.container-lifecycle]] +== Lifecycle of managed containers + +If you have used the annotations and extensions provided by Testcontainers, then the lifecycle of container instances is managed by the Testcontainers. +Please refer to the {url-testcontainres-java-doc}[Testcontainers official documentation] for the information about lifecycle of the containers, when managed by the Testcontainers. + +When the containers are managed by Spring as beans, then the lifecycle is clearly defined by Spring. +The container beans are created and started before the beans of other types are created. +This process ensures that any beans, which rely on functionality provided by the containers, can use those functionalities. + +The test containers can be started multiple times. +Like any other beans the test containers are created and started once per application context managed by the TestContext Framework. +For details about how TestContext framework manages the underlying application contexts and beans therein, please refer to the {url-spring-framework-docs}[official Spring documentation]. + +The container beans are stopped after the destruction of beans of other types. +This ensures that any beans depending on the functionalities provided by the containers are cleaned up first. + +TIP: When your application beans rely on functionality of containers, prefer configuring the containers as Spring beans. +When containers are managed as Spring beans, then Spring framework ensures that upon start the container beans are started before any beans relying on them. +On shutdown the application beans depending on container functionalities are cleaned up first, and only then are the containers shut down. + +NOTE: Having containers managed by Testcontainers instead of as Spring beans provides no guarantee of order in which beans and containers will shutdown. +It can happen that containers are shutdown before the beans relying on container functionality are cleaned up. +This can lead to exceptions being thrown by client beans due to loss of connection for example. + +The containers are stopped as part of the application shutdown process, managed by the TestContext framework. +When the application context gets shutdown, the containers are shutdown as well. +This usually happens after all tests using that specific cached application context have finished executing, but may happen earlier depending on the caching behavior configured in TestContext Framework. + +It is important to note that a single test container instance can be, and often is, retained across execution of tests from multiple test classes. + [[testing.testcontainers.service-connections]] diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.java new file mode 100644 index 00000000000..7a1e4e5e7c8 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2025 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.testing.testcontainers.beandeclaration; + +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.utility.DockerImageName; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; + +@TestConfiguration(proxyBeanMethods = false) +class BeanDeclarationConfig { + + @ServiceConnection + @Bean + MongoDBContainer container() { + return new MongoDBContainer(DockerImageName.parse("mongo:latest")); + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.java new file mode 100644 index 00000000000..4f98ba476f0 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2025 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.testing.testcontainers.beandeclaration; + +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.MongoDBContainer; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +@SpringBootTest +@Import(BeanDeclarationConfig.class) +class SpringTest { + + @Autowired + private MongoDBContainer mongo; + + @Test + void doTest() { + System.out.println("Mongo db is running: " + this.mongo.isRunning()); + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyConfiguration.java new file mode 100644 index 00000000000..2b3857fb9cc --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyConfiguration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2012-2025 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.testing.testcontainers.importcontainers; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.context.ImportTestcontainers; + +@TestConfiguration(proxyBeanMethods = false) +@ImportTestcontainers(MyInterface.class) +class MyConfiguration { + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyInterface.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyInterface.java new file mode 100644 index 00000000000..b00f693277d --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyInterface.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2025 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.testing.testcontainers.importcontainers; + +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.containers.Neo4jContainer; +import org.testcontainers.junit.jupiter.Container; + +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +interface MyInterface { + + @Container + @ServiceConnection + MongoDBContainer mongoContainer = new MongoDBContainer("mongo:5.0"); + + @Container + @ServiceConnection + Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:5"); + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.kt new file mode 100644 index 00000000000..ddbce31e75d --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.kt @@ -0,0 +1,17 @@ +package org.springframework.boot.docs.testing.testcontainers.beandeclaration + +import org.springframework.boot.test.context.TestConfiguration +import org.springframework.boot.testcontainers.service.connection.ServiceConnection +import org.springframework.context.annotation.Bean +import org.testcontainers.containers.MongoDBContainer +import org.testcontainers.utility.DockerImageName + + +@TestConfiguration(proxyBeanMethods = false) +internal class BeanDeclarationConfig { + @ServiceConnection + @Bean + fun container(): MongoDBContainer { + return MongoDBContainer(DockerImageName.parse("mongo:latest")) + } +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.kt new file mode 100644 index 00000000000..edb36d9cf08 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.kt @@ -0,0 +1,19 @@ +package org.springframework.boot.docs.testing.testcontainers.beandeclaration + +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.context.annotation.Import +import org.testcontainers.containers.MongoDBContainer + +@SpringBootTest +@Import(BeanDeclarationConfig::class) +class SpringTest { + @Autowired + private val mongo: MongoDBContainer? = null + + @Test + fun doTest() { + println("Mongo db is running: " + mongo!!.isRunning) + } +} \ No newline at end of file diff --git a/src/checkstyle/checkstyle-suppressions.xml b/src/checkstyle/checkstyle-suppressions.xml index b1d096a8711..de6bdce36e0 100644 --- a/src/checkstyle/checkstyle-suppressions.xml +++ b/src/checkstyle/checkstyle-suppressions.xml @@ -82,6 +82,7 @@ + From 8814d8a7dcd39c31eaab2f027a74acd9b2fc979d Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 5 May 2025 22:03:01 -0700 Subject: [PATCH 2/2] Polish 'Document methods of starting Testcontainer containers' See gh-44187 --- .../antora-asciidoc-attributes.properties | 2 +- .../pages/testing/testcontainers.adoc | 99 ++++++++++--------- .../MyContainers.java} | 8 +- .../MyTestConfiguration.java} | 6 +- .../MyIntegrationTests.java | 6 +- .../MyIntegrationTests.java | 4 +- .../MyIntegrationTests.java} | 10 +- .../MyTestConfiguration.java} | 10 +- .../beandeclaration/BeanDeclarationConfig.kt | 17 ---- .../beandeclaration/SpringTest.kt | 19 ---- .../dynamicproperties/MyIntegrationTests.kt | 2 +- .../MyContainers.kt | 35 +++++++ .../MyTestConfiguration.kt | 26 +++++ .../MyIntegrationTests.kt | 7 +- .../serviceconnections/MyIntegrationTests.kt | 2 +- .../MyRedisConfiguration.kt | 2 + .../springbeans/MyIntegrationTests.kt | 36 +++++++ .../springbeans/MyTestConfiguration.kt | 31 ++++++ 18 files changed, 208 insertions(+), 114 deletions(-) rename spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/{importcontainers/MyInterface.java => importingconfigurationinterfaces/MyContainers.java} (86%) rename spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/{importcontainers/MyConfiguration.java => importingconfigurationinterfaces/MyTestConfiguration.java} (89%) rename spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/{vanilla => junitextension}/MyIntegrationTests.java (85%) rename spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/{beandeclaration/SpringTest.java => springbeans/MyIntegrationTests.java} (81%) rename spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/{beandeclaration/BeanDeclarationConfig.java => springbeans/MyTestConfiguration.java} (74%) delete mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.kt delete mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.kt create mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyContainers.kt create mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyTestConfiguration.kt rename spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/{vanilla => junitextension}/MyIntegrationTests.kt (86%) create mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/springbeans/MyIntegrationTests.kt create mode 100644 spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/springbeans/MyTestConfiguration.kt diff --git a/buildSrc/src/main/resources/org/springframework/boot/build/antora/antora-asciidoc-attributes.properties b/buildSrc/src/main/resources/org/springframework/boot/build/antora/antora-asciidoc-attributes.properties index e2098cbe411..d0fb5f6cae2 100644 --- a/buildSrc/src/main/resources/org/springframework/boot/build/antora/antora-asciidoc-attributes.properties +++ b/buildSrc/src/main/resources/org/springframework/boot/build/antora/antora-asciidoc-attributes.properties @@ -75,7 +75,7 @@ url-spring-data-rest-docs=https://docs.spring.io/spring-data/rest/reference/{ant url-spring-data-rest-site=https://spring.io/projects/spring-data-rest url-spring-data-rest-javadoc=https://docs.spring.io/spring-data/rest/docs/{dotxversion-spring-data-rest}/api url-spring-data-site=https://spring.io/projects/spring-data -url-testcontainers-java-doc=https://java.testcontainers.org +url-testcontainers-docs=https://java.testcontainers.org url-testcontainers-activemq-javadoc=https://javadoc.io/doc/org.testcontainers/activemq/{version-testcontainers-activemq} url-testcontainers-cassandra-javadoc=https://javadoc.io/doc/org.testcontainers/cassandra/{version-testcontainers-cassandra} url-testcontainers-couchbase-javadoc=https://javadoc.io/doc/org.testcontainers/couchbase/{version-testcontainers-couchbase} diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc index 5325e6a85dd..5cde95b5396 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/testcontainers.adoc @@ -8,85 +8,90 @@ Testcontainers is especially useful for writing integration tests that talk to a In following sections we will describe some of the methods you can use to integrate Testcontainers with your tests. +[[testing.testcontainers.spring-beans]] +== Using Spring Beans -[[testing.testcontainers.via-junit-extension]] -== Using via @Testcontainers JUnit5 extension +The containers provided by Testcontainers can be managed by Spring Boot as beans. -The Testcontainers provides JUnit5 extensions, which can be used to manage containers in your tests. -The extension is activated by applying the `@Testcontainers` annotation from Testcontainers to your test class. +To declare a container as a bean, add a javadoc:org.springframework.context.annotation.Bean[format=annotation] method to your test configuration: -Testcontainers can be used in a Spring Boot test as follows: +include-code::MyTestConfiguration[] -include-code::vanilla/MyIntegrationTests[] +You can then inject and use the container by importing the configuration class in the test class: -This will start up a Docker container running Neo4j (if Docker is running locally) before any of the tests are run. -In most cases, you will need to configure the application to connect to the service running in the container. +include-code::MyIntegrationTests[] -In this case the lifecycle of the container instance is managed by Testcontainers, as described in official documentation. +TIP: This method of managing containers is often used in combination with xref:#testing.testcontainers.service-connections[service connection annotations]. -[[testing.testcontainers.via-spring-beans]] -== Using via Spring managed beans -The containers provided by Testcontainers can be managed by Spring Boot as beans. -This method of managing contains can be used in combination with javadoc:org.springframework.boot.testcontainers.service.connection.ServiceConnection[format=annotation]. +[[testing.testcontainers.junit-extension]] +== Using the JUnit Extension -To use Testcontainer contains as Spring beans we need to create a configuration class declaring the container as bean: +Testcontainers provides a JUnit extension which can be used to manage containers in your tests. +The extension is activated by applying the javadoc:org.testcontainers.junit.jupiter.Testcontainers[format=annotation] annotation from Testcontainers to your test class. -include-code::beandeclaration/BeanDeclarationConfig[] +You can then use the javadoc:org.testcontainers.junit.jupiter.Container[format=annotation] annotation on static container fields. -then we can start the container by importing the configuration class in the test class: +The javadoc:org.testcontainers.junit.jupiter.Testcontainers[format=annotation] annotation can be used on vanilla JUnit tests, or in combination with javadoc:org.springframework.boot.test.context.SpringBootTest[format=annotation]: -include-code::beandeclaration/SpringTest[] +include-code::MyIntegrationTests[] +The example above will start up a Neo4j container before any of the tests are run. +The lifecycle of the container instance is managed by Testcontainers, as described in {url-testcontainers-docs}/test_framework_integration/junit_5/#extension[their official documentation]. -[[testing.testcontainers.via-declaration-classes]] -== Using via importing container declaration classes +NOTE: In most cases, you will additionally need to configure the application to connect to the service running in the container. -A common pattern with Testcontainers is to declare the Container instances as static fields in an interface. -For example the following interface `MyInterface` declares two containers, one named `mongo` of type MongoDB and another named `neo` of type Neo4j: -include-code::importcontainers/MyInterface[] -When you have containers declared in this way, then you can have these containers managed by Spring Boot as beans. -All that is needed to do that is adding javadoc:org.springframework.boot.testcontainers.context.ImportTestcontainers[format=annotation] to your configuration class as in: +[[testing.testcontainers.importing-configuration-interfaces]] +== Importing Container Configuration Interfaces -include-code::importcontainers/MyConfiguration[] +A common pattern with Testcontainers is to declare the container instances as static fields in an interface. -TIP: Using interfaces for declaring contains helps with reuse. -When containers are declared in an interface, this can be reused in your javadoc:org.springframework.context.annotation.Configuration[format=annotation] classes and in test classes. +For example, the following interface declares two containers, one named `mongo` of type javadoc:org.testcontainers.containers.MongoDBContainer[] and another named `neo4j` of type javadoc:org.testcontainers.containers.Neo4jContainer.Neo4jContainer[]: +include-code::MyContainers[] -[[test.testcontainers.container-lifecycle]] -== Lifecycle of managed containers +When you have containers declared in this way, you can reuse their configuration in multiple tests by having the test classes implement the interface. + +It's also possible to use the same interface configuration in your Spring Boot tests. +To do so, add javadoc:org.springframework.boot.testcontainers.context.ImportTestcontainers[format=annotation] to your test configuration class: + +include-code::MyTestConfiguration[] -If you have used the annotations and extensions provided by Testcontainers, then the lifecycle of container instances is managed by the Testcontainers. -Please refer to the {url-testcontainres-java-doc}[Testcontainers official documentation] for the information about lifecycle of the containers, when managed by the Testcontainers. -When the containers are managed by Spring as beans, then the lifecycle is clearly defined by Spring. -The container beans are created and started before the beans of other types are created. -This process ensures that any beans, which rely on functionality provided by the containers, can use those functionalities. -The test containers can be started multiple times. -Like any other beans the test containers are created and started once per application context managed by the TestContext Framework. -For details about how TestContext framework manages the underlying application contexts and beans therein, please refer to the {url-spring-framework-docs}[official Spring documentation]. +[[testing.testcontainers.lifecycle]] +== Lifecycle of Managed Containers -The container beans are stopped after the destruction of beans of other types. -This ensures that any beans depending on the functionalities provided by the containers are cleaned up first. +If you have used the annotations and extensions provided by Testcontainers, then the lifecycle of container instances is managed entirely by Testcontainers. +Please refer to the {url-testcontainers-docs}[offical Testcontainers documentation] for the information. -TIP: When your application beans rely on functionality of containers, prefer configuring the containers as Spring beans. -When containers are managed as Spring beans, then Spring framework ensures that upon start the container beans are started before any beans relying on them. -On shutdown the application beans depending on container functionalities are cleaned up first, and only then are the containers shut down. +When the containers are managed by Spring as beans, then their lifecycle is managed by Spring: -NOTE: Having containers managed by Testcontainers instead of as Spring beans provides no guarantee of order in which beans and containers will shutdown. +* Container beans are created and started before all other beans. + +* Container beans are stopped after the destruction of all other beans. + +This process ensures that any beans, which rely on functionality provided by the containers, can use those functionalities. +It also ensures that they are cleaned up whilst the container is still available. + +TIP: When your application beans rely on functionality of containers, prefer configuring the containers as Spring beans to ensure the correct lifecycle behavior. + +NOTE: Having containers managed by Testcontainers instead of as Spring beans provides no guarantee of the order in which beans and containers will shutdown. It can happen that containers are shutdown before the beans relying on container functionality are cleaned up. -This can lead to exceptions being thrown by client beans due to loss of connection for example. +This can lead to exceptions being thrown by client beans, for example, due to loss of connection. + +Container beans are created and started once per application context managed by Spring's TestContext Framework. +For details about how TestContext Framework manages the underlying application contexts and beans therein, please refer to the {url-spring-framework-docs}[Spring Framework documentation]. -The containers are stopped as part of the application shutdown process, managed by the TestContext framework. +Container beans are stopped as part of the TestContext Framework's standard application context shutdown process. When the application context gets shutdown, the containers are shutdown as well. -This usually happens after all tests using that specific cached application context have finished executing, but may happen earlier depending on the caching behavior configured in TestContext Framework. +This usually happens after all tests using that specific cached application context have finished executing. +It may also happen earlier, depending on the caching behavior configured in TestContext Framework. -It is important to note that a single test container instance can be, and often is, retained across execution of tests from multiple test classes. +NOTE: A single test container instance can, and often is, retained across execution of tests from multiple test classes. diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyInterface.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyContainers.java similarity index 86% rename from spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyInterface.java rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyContainers.java index b00f693277d..57bb3b3e73c 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyInterface.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyContainers.java @@ -14,22 +14,18 @@ * limitations under the License. */ -package org.springframework.boot.docs.testing.testcontainers.importcontainers; +package org.springframework.boot.docs.testing.testcontainers.importingconfigurationinterfaces; import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.containers.Neo4jContainer; import org.testcontainers.junit.jupiter.Container; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; - -interface MyInterface { +interface MyContainers { @Container - @ServiceConnection MongoDBContainer mongoContainer = new MongoDBContainer("mongo:5.0"); @Container - @ServiceConnection Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:5"); } diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyTestConfiguration.java similarity index 89% rename from spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyConfiguration.java rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyTestConfiguration.java index 2b3857fb9cc..ce41dc1fe86 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importcontainers/MyConfiguration.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyTestConfiguration.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package org.springframework.boot.docs.testing.testcontainers.importcontainers; +package org.springframework.boot.docs.testing.testcontainers.importingconfigurationinterfaces; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.context.ImportTestcontainers; @TestConfiguration(proxyBeanMethods = false) -@ImportTestcontainers(MyInterface.class) -class MyConfiguration { +@ImportTestcontainers(MyContainers.class) +class MyTestConfiguration { } diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/vanilla/MyIntegrationTests.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/junitextension/MyIntegrationTests.java similarity index 85% rename from spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/vanilla/MyIntegrationTests.java rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/junitextension/MyIntegrationTests.java index 1bfe8857cc0..dc35d131821 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/vanilla/MyIntegrationTests.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/junitextension/MyIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.docs.testing.testcontainers.vanilla; +package org.springframework.boot.docs.testing.testcontainers.junitextension; import org.junit.jupiter.api.Test; import org.testcontainers.containers.Neo4jContainer; @@ -32,7 +32,7 @@ class MyIntegrationTests { @Test void myTest() { - // ... + /**/ System.out.println(neo4j); } } diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyIntegrationTests.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyIntegrationTests.java index 8827213caa4..334edc561d5 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyIntegrationTests.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -34,7 +34,7 @@ class MyIntegrationTests { @Test void myTest() { - // ... + /**/ System.out.println(neo4j); } } diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/springbeans/MyIntegrationTests.java similarity index 81% rename from spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.java rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/springbeans/MyIntegrationTests.java index 4f98ba476f0..21db9a72de0 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/springbeans/MyIntegrationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.docs.testing.testcontainers.beandeclaration; +package org.springframework.boot.docs.testing.testcontainers.springbeans; import org.junit.jupiter.api.Test; import org.testcontainers.containers.MongoDBContainer; @@ -24,15 +24,15 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; @SpringBootTest -@Import(BeanDeclarationConfig.class) -class SpringTest { +@Import(MyTestConfiguration.class) +class MyIntegrationTests { @Autowired private MongoDBContainer mongo; @Test - void doTest() { - System.out.println("Mongo db is running: " + this.mongo.isRunning()); + void myTest() { + /**/ System.out.println(this.mongo); } } diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/springbeans/MyTestConfiguration.java similarity index 74% rename from spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.java rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/springbeans/MyTestConfiguration.java index 7a1e4e5e7c8..944eab5ca93 100644 --- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.java +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/testing/testcontainers/springbeans/MyTestConfiguration.java @@ -14,22 +14,20 @@ * limitations under the License. */ -package org.springframework.boot.docs.testing.testcontainers.beandeclaration; +package org.springframework.boot.docs.testing.testcontainers.springbeans; import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.utility.DockerImageName; import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; @TestConfiguration(proxyBeanMethods = false) -class BeanDeclarationConfig { +class MyTestConfiguration { - @ServiceConnection @Bean - MongoDBContainer container() { - return new MongoDBContainer(DockerImageName.parse("mongo:latest")); + MongoDBContainer mongoDbContainer() { + return new MongoDBContainer(DockerImageName.parse("mongo:5.0")); } } diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.kt deleted file mode 100644 index ddbce31e75d..00000000000 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/BeanDeclarationConfig.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.springframework.boot.docs.testing.testcontainers.beandeclaration - -import org.springframework.boot.test.context.TestConfiguration -import org.springframework.boot.testcontainers.service.connection.ServiceConnection -import org.springframework.context.annotation.Bean -import org.testcontainers.containers.MongoDBContainer -import org.testcontainers.utility.DockerImageName - - -@TestConfiguration(proxyBeanMethods = false) -internal class BeanDeclarationConfig { - @ServiceConnection - @Bean - fun container(): MongoDBContainer { - return MongoDBContainer(DockerImageName.parse("mongo:latest")) - } -} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.kt deleted file mode 100644 index edb36d9cf08..00000000000 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/beandeclaration/SpringTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.springframework.boot.docs.testing.testcontainers.beandeclaration - -import org.junit.jupiter.api.Test -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.context.annotation.Import -import org.testcontainers.containers.MongoDBContainer - -@SpringBootTest -@Import(BeanDeclarationConfig::class) -class SpringTest { - @Autowired - private val mongo: MongoDBContainer? = null - - @Test - fun doTest() { - println("Mongo db is running: " + mongo!!.isRunning) - } -} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/dynamicproperties/MyIntegrationTests.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/dynamicproperties/MyIntegrationTests.kt index ca5697de93c..cf1b16b7e44 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/dynamicproperties/MyIntegrationTests.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/dynamicproperties/MyIntegrationTests.kt @@ -29,7 +29,7 @@ class MyIntegrationTests { @Test fun myTest() { - // ... + /**/ println() } companion object { diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyContainers.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyContainers.kt new file mode 100644 index 00000000000..e778cd68987 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyContainers.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2012-2025 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.testing.testcontainers.importingconfigurationinterfaces + +import org.testcontainers.containers.MongoDBContainer +import org.testcontainers.containers.Neo4jContainer +import org.testcontainers.junit.jupiter.Container + +interface MyContainers { + + companion object { + + @Container + val mongoContainer: MongoDBContainer = MongoDBContainer("mongo:5.0") + + @Container + val neo4jContainer: Neo4jContainer<*> = Neo4jContainer("neo4j:5") + + } + +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyTestConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyTestConfiguration.kt new file mode 100644 index 00000000000..fd8edc8e3e2 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/importingconfigurationinterfaces/MyTestConfiguration.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2012-2025 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.testing.testcontainers.importingconfigurationinterfaces + +import org.springframework.boot.test.context.TestConfiguration +import org.springframework.boot.testcontainers.context.ImportTestcontainers + +@TestConfiguration(proxyBeanMethods = false) +@ImportTestcontainers(MyContainers::class) +class MyTestConfiguration { + +} diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/vanilla/MyIntegrationTests.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/junitextension/MyIntegrationTests.kt similarity index 86% rename from spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/vanilla/MyIntegrationTests.kt rename to spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/junitextension/MyIntegrationTests.kt index f2215052995..477bc15cec8 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/vanilla/MyIntegrationTests.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/junitextension/MyIntegrationTests.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.docs.testing.testcontainers.vanilla +package org.springframework.boot.docs.testing.testcontainers.junitextension import org.junit.jupiter.api.Test; import org.testcontainers.containers.Neo4jContainer; @@ -22,7 +22,6 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection @Testcontainers @SpringBootTest @@ -30,13 +29,15 @@ class MyIntegrationTests { @Test fun myTest() { - // ... + /**/ println() } companion object { + @Container @JvmStatic val neo4j = Neo4jContainer("neo4j:5"); + } } diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyIntegrationTests.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyIntegrationTests.kt index f50a262ad32..6134cbbe576 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyIntegrationTests.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyIntegrationTests.kt @@ -30,7 +30,7 @@ class MyIntegrationTests { @Test fun myTest() { - // ... + /**/ println() } companion object { diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyRedisConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyRedisConfiguration.kt index 35f7027cfdf..e7b10768227 100644 --- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyRedisConfiguration.kt +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/serviceconnections/MyRedisConfiguration.kt @@ -23,9 +23,11 @@ import org.testcontainers.containers.GenericContainer @TestConfiguration(proxyBeanMethods = false) class MyRedisConfiguration { + @Bean @ServiceConnection(name = "redis") fun redisContainer(): GenericContainer<*> { return GenericContainer("redis:7") } + } \ No newline at end of file diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/springbeans/MyIntegrationTests.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/springbeans/MyIntegrationTests.kt new file mode 100644 index 00000000000..8d0f1cc9302 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/springbeans/MyIntegrationTests.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2012-2025 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.testing.testcontainers.springbeans + +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.context.annotation.Import +import org.testcontainers.containers.MongoDBContainer + +@SpringBootTest +@Import(MyTestConfiguration::class) +class MyIntegrationTests { + + @Autowired + private val mongo: MongoDBContainer? = null + + @Test + fun myTest() { + /**/ println() + } + +} \ No newline at end of file diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/springbeans/MyTestConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/springbeans/MyTestConfiguration.kt new file mode 100644 index 00000000000..19b9f87c1e2 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/testing/testcontainers/springbeans/MyTestConfiguration.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2012-2025 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.testing.testcontainers.springbeans + +import org.springframework.boot.test.context.TestConfiguration +import org.springframework.context.annotation.Bean +import org.testcontainers.containers.MongoDBContainer +import org.testcontainers.utility.DockerImageName + +@TestConfiguration(proxyBeanMethods = false) +class MyTestConfiguration { + + @Bean + fun mongoDbContainer(): MongoDBContainer { + return MongoDBContainer(DockerImageName.parse("mongo:5.0")) + } + +} \ No newline at end of file