Skip to content

Commit

Permalink
Merge branch '3.1.x'
Browse files Browse the repository at this point in the history
Closes gh-38336
  • Loading branch information
mhalbritter committed Nov 13, 2023
2 parents fc25d19 + 5a3e588 commit 260a0b6
Show file tree
Hide file tree
Showing 21 changed files with 123 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1037,3 +1037,9 @@ deployment.installing.nix-services.script-customization=deployment.installing.in
deployment.installing.nix-services.script-customization.when-written=deployment.installing.init-d.script-customization.when-written
deployment.installing.nix-services.script-customization.when-running=deployment.installing.init-d.script-customization.when-running
deployment.installing.nix-services.script-customization.when-running.conf-file=deployment.installing.init-d.script-customization.when-running.conf-file

# gh-35856
features.testing.testcontainers.at-development-time=features.testcontainers.at-development-time
features.testing.testcontainers.at-development-time.dynamic-properties=features.testcontainers.at-development-time.dynamic-properties
features.testing.testcontainers.at-development-time.importing-container-declarations=features.testcontainers.at-development-time.importing-container-declarations
features.testing.testcontainers.at-development-time.devtools=features.testcontainers.at-development-time.devtools
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ include::features/testing.adoc[]

include::features/docker-compose.adoc[]

include::features/testcontainers.adoc[]

include::features/developing-auto-configuration.adoc[]

include::features/kotlin.adoc[]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
[[features.testcontainers]]
== Testcontainers Support
As well as <<features#features.testing.testcontainers, using Testcontainers for integration testing>>, it's also possible to use them at development time.
The next sections will provide more details about that.



[[features.testcontainers.at-development-time]]
=== Using Testcontainers at Development Time
This approach allows developers to quickly start containers for the services that the application depends on, removing the need to manually provision things like database servers.
Using Testcontainers in this way provides functionality similar to Docker Compose, except that your container configuration is in Java rather than YAML.

To use Testcontainers at development time you need to launch your application using your "`test`" classpath rather than "`main`".
This will allow you to access all declared test dependencies and give you a natural place to write your test configuration.

To create a test launchable version of your application you should create an "`Application`" class in the `src/test` directory.
For example, if your main application is in `src/main/java/com/example/MyApplication.java`, you should create `src/test/java/com/example/TestMyApplication.java`

The `TestMyApplication` class can use the `SpringApplication.from(...)` method to launch the real application:

include::code:launch/TestMyApplication[]

You'll also need to define the `Container` instances that you want to start along with your application.
To do this, you need to make sure that the `spring-boot-testcontainers` module has been added as a `test` dependency.
Once that has been done, you can create a `@TestConfiguration` class that declares `@Bean` methods for the containers you want to start.

You can also annotate your `@Bean` methods with `@ServiceConnection` in order to create `ConnectionDetails` beans.
See <<features#features.testing.testcontainers.service-connections, the service connections>> section for details of the supported technologies.

A typical Testcontainers configuration would look like this:

include::code:test/MyContainersConfiguration[]

NOTE: The lifecycle of `Container` beans is automatically managed by Spring Boot.
Containers will be started and stopped automatically.

TIP: You can use the configprop:spring.testcontainers.beans.startup[] property to change how containers are started.
By default `sequential` startup is used, but you may also choose `parallel` if you wish to start multiple containers in parallel.

Once you have defined your test configuration, you can use the `with(...)` method to attach it to your test launcher:

include::code:test/TestMyApplication[]

You can now launch `TestMyApplication` as you would any regular Java `main` method application to start your application and the containers that it needs to run.

TIP: You can use the Maven goal `spring-boot:test-run` or the Gradle task `bootTestRun` to do this from the command line.



[[features.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 <<features#features.testing.testcontainers.dynamic-properties,`@DynamicPropertySource` annotation>> 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.testcontainers.at-development-time.importing-container-declarations]]
==== Importing Testcontainer Declaration Classes
A common pattern when using Testcontainers is to declare `Container` instances as static fields.
Often these fields are defined directly on the test class.
They can also be declared on a parent class or on an interface that the test implements.

For example, the following `MyContainers` interface declares `mongo` and `neo4j` containers:

include::code:MyContainers[]

If you already have containers defined in this way, or you just prefer this style, you can import these declaration classes rather than defining you containers as `@Bean` methods.
To do so, add the `@ImportTestcontainers` annotation to your test configuration class:

include::code:MyContainersConfiguration[]

TIP: You can use the `@ServiceConnection` annotation on `Container` fields to establish service connections.
You can also add <<features#features.testing.testcontainers.dynamic-properties,`@DynamicPropertySource` annotated methods>> to your declaration class.



[[features.testcontainers.at-development-time.devtools]]
==== Using DevTools with Testcontainers at Development Time
When using devtools, you can annotate beans and bean methods with `@RestartScope`.
Such beans won't be recreated when the devtools restart the application.
This is especially useful for Testcontainer `Container` beans, as they keep their state despite the application restart.

include::code:MyContainersConfiguration[]

WARNING: If you're using Gradle and want to use this feature, you need to change the configuration of the `spring-boot-devtools` dependency from `developmentOnly` to `testImplementation`.
With the default scope of `developmentOnly`, the `bootTestRun` task will not pick up changes in your code, as the devtools are not active.
Original file line number Diff line number Diff line change
Expand Up @@ -1055,96 +1055,6 @@ The above configuration allows Neo4j-related beans in the application to communi



[[features.testing.testcontainers.at-development-time]]
==== Using Testcontainers at Development Time
As well as using Testcontainers for integration testing, it's also possible to use them at development time.
This approach allows developers to quickly start containers for the services that the application depends on, removing the need to manually provision things like database servers.
Using Testcontainers in this way provides functionality similar to Docker Compose, except that your container configuration is in Java rather than YAML.

To use Testcontainers at development time you need to launch your application using your "`test`" classpath rather than "`main`".
This will allow you to access all declared test dependencies and give you a natural place to write your test configuration.

To create a test launchable version of your application you should create an "`Application`" class in the `src/test` directory.
For example, if your main application is in `src/main/java/com/example/MyApplication.java`, you should create `src/test/java/com/example/TestMyApplication.java`

The `TestMyApplication` class can use the `SpringApplication.from(...)` method to launch the real application:

include::code:launch/TestMyApplication[]

You'll also need to define the `Container` instances that you want to start along with your application.
To do this, you need to make sure that the `spring-boot-testcontainers` module has been added as a `test` dependency.
Once that has been done, you can create a `@TestConfiguration` class that declares `@Bean` methods for the containers you want to start.

You can also annotate your `@Bean` methods with `@ServiceConnection` in order to create `ConnectionDetails` beans.
See <<features#features.testing.testcontainers.service-connections, the service connections>> section above for details of the supported technologies.

A typical Testcontainers configuration would look like this:

include::code:test/MyContainersConfiguration[]

NOTE: The lifecycle of `Container` beans is automatically managed by Spring Boot.
Containers will be started and stopped automatically.

TIP: You can use the configprop:spring.testcontainers.beans.startup[] property to change how containers are started.
By default `sequential` startup is used, but you may also choose `parallel` if you wish to start multiple containers in parallel.

Once you have defined your test configuration, you can use the `with(...)` method to attach it to your test launcher:

include::code:test/TestMyApplication[]

You can now launch `TestMyApplication` as you would any regular Java `main` method application to start your application and the containers that it needs to run.

TIP: You can use the Maven goal `spring-boot:test-run` or the Gradle task `bootTestRun` to do this from the command line.



[[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 <<features#features.testing.testcontainers.dynamic-properties,`@DynamicPropertySource` annotation>> 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.testcontainers.at-development-time.importing-container-declarations]]
===== Importing Testcontainer Declaration Classes
A common pattern when using Testcontainers is to declare `Container` instances as static fields.
Often these fields are defined directly on the test class.
They can also be declared on a parent class or on an interface that the test implements.

For example, the following `MyContainers` interface declares `mongo` and `neo4j` containers:

include::code:MyContainers[]

If you already have containers defined in this way, or you just prefer this style, you can import these declaration classes rather than defining you containers as `@Bean` methods.
To do so, add the `@ImportTestcontainers` annotation to your test configuration class:

include::code:MyContainersConfiguration[]

TIP: You can use the `@ServiceConnection` annotation on `Container` fields to establish service connections.
You can also add <<features#features.testing.testcontainers.dynamic-properties,`@DynamicPropertySource` annotated methods>> to your declaration class.



[[features.testing.testcontainers.at-development-time.devtools]]
===== Using DevTools with Testcontainers at Development Time
When using devtools, you can annotate beans and bean methods with `@RestartScope`.
Such beans won't be recreated when the devtools restart the application.
This is especially useful for Testcontainer `Container` beans, as they keep their state despite the application restart.

include::code:MyContainersConfiguration[]

WARNING: If you're using Gradle and want to use this feature, you need to change the configuration of the `spring-boot-devtools` dependency from `developmentOnly` to `testAndDevelopmentOnly`.
With the default scope of `developmentOnly`, the `bootTestRun` task will not pick up changes in your code, as the devtools are not active.



[[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`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.devtools;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.devtools;

import org.testcontainers.containers.MongoDBContainer;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.dynamicproperties;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.dynamicproperties;

import org.testcontainers.containers.MongoDBContainer;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.importingcontainerdeclarations;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.importingcontainerdeclarations;

import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.containers.Neo4jContainer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.importingcontainerdeclarations;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.importingcontainerdeclarations;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.test;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.launch;

public class MyApplication {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.launch;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.launch;

import org.springframework.boot.SpringApplication;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.launch;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test;

public class MyApplication {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.test;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test;

import org.testcontainers.containers.Neo4jContainer;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.test;
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test;

import org.springframework.boot.SpringApplication;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.devtools
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.devtools

import org.springframework.boot.devtools.restart.RestartScope
import org.springframework.boot.test.context.TestConfiguration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.dynamicproperties
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.dynamicproperties

import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean;
Expand All @@ -32,4 +32,4 @@ class MyContainersConfiguration {
return container
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.importingcontainerdeclarations
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.importingcontainerdeclarations

import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.testcontainers.context.ImportTestcontainers
Expand All @@ -23,4 +23,4 @@ import org.springframework.boot.testcontainers.context.ImportTestcontainers
@ImportTestcontainers(MyContainers::class)
class MyContainersConfiguration {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.launch
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.launch

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.docs.features.springapplication.MyApplication
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.launch
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.launch

import org.springframework.boot.fromApplication

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.test
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.docs.features.springapplication.MyApplication
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.test

import org.testcontainers.containers.Neo4jContainer
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test

import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.testcontainers.service.connection.ServiceConnection
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Bean
import org.testcontainers.containers.Neo4jContainer

@TestConfiguration(proxyBeanMethods = false)
class MyContainersConfiguration {
Expand All @@ -31,4 +30,4 @@ class MyContainersConfiguration {
return Neo4jContainer("neo4j:5")
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.docs.features.testing.testcontainers.atdevelopmenttime.test
package org.springframework.boot.docs.features.testcontainers.atdevelopmenttime.test

import org.springframework.boot.fromApplication
import org.springframework.boot.with
Expand Down

0 comments on commit 260a0b6

Please sign in to comment.