Everything you need to know about Testcontainers integration on Spring Boot 3.1

In my previous blog, I presented you the Testcontainers library. In this blog, I'm going to show the improvements made since version 3.1 of Spring Boot that makes it easier to use Testcontainers in our applications testing.

How to use Testcontainers

We will start with an example of Testcontainers usage. Our demo is a Spring Boot application that uses a PostgreSQL database. In order to run our tests, we include the following Maven dependencies:

JAVA

Now we can create our tests. We annotate the test class with @Testcontainers annotation. Then we create a PostgreSQLContainer and use a DynamicPropertyRegistry bean to configure that datasource with the settings retrieved from the PostgreSQL container.

JAVA

How you can simplify the tests using Service Connections

Beginning from Spring Boot version 3.1, the annotation @ServiceConnection can be used on the container instance fields of our tests:

JAVA

The @ServiceConnection instructs Spring to discover the type of container that is annotated and create a ConnectionDetails bean for it, or more specifically, a JdbcConnectionDetails bean. The type of container is discovered based on the container module implementation (PostgreSQLContainer in the example above) or the image name (in case of GenericContainer usage). The PostgreSQL spring boot auto configuration will consume the connection details bean and configure the datasource to connect to the PostgreSQL database.

This replaces the need for the @DynamicPropertySource code, so, it can be removed.

By using the @ServiceConnection annotation, you write less code, which is less error-prone; and you don’t need to remember all properties needed to configure the connection.

Using Testcontainers during development

Tests run fine. What if we want to run our application locally during development? It will not work since we don’t have a PostgreSQL database available. We must first install and/or start such a database. Fortunately, this has been simplified with Spring Boot 3.1. We only need to enable development mode with Testcontainers. First, we add a new Maven dependency in the test scope:

JAVA

Now, we can create a @TestConfiguration class where we will define beans for the containers that we require to run our application. In our example above, we need a PostgreSQL container:

JAVA

Note that the container is annotated with @ServiceConnection so that Spring Boot will use it create the connection to the database. Spring Boot will also manage the lifecycle of this container. The container is started when the application starts and is shut down when the application stops.

After that, we can create a new “main” class in the test sources to start the application using the container configured above:

JAVA

The class above uses SpringApplication.from(…) method to launch the real DemoApplication, but using the containers defined in the DemoTestConfiguration class. You can run this class from your preferred IDE, but the spring-boot maven plugin also provides a new goal that will execute this main class

JAVA

Once the app starts you will see that the PostgreSQL container is up and running and connection to it is established.

Note that the container will be shut down every time the application restarts. That is not a desired situation, since it takes time during the development period, and you may lose data that was in your database.

To prevent this, we can add Spring Devtools to our maven dependencies:

JAVA

And then annotate the PostgreSQL bean with the @RestartScope annotation:

JAVA

The above will prevent the container to be shut down when the application restarts.

Sharing containers with multiple applications

In the previous examples, I presented a demo application that connects to a database using a single container. Suppose we want to develop and test multiple applications that connect to the same PostgreSQL database. Then we do similar as before, except that we need the container test configuration available for all applications and this time we will mark the container as reusable:

JAVA

By setting the container as reusable, it will not be stopped when the application is shut down. Note that not all container modules support the reusable option.

Conclusion

Spring Boot 3.1 brings lots of improvements to support the usage of Testcontainers, enforcing the advice that Testcontainers is a useful option when it comes to using containers for testing, and now also for development. I hope this post will help you to take advantage of these improvements.

The demos presented in this article are on GitHub.

About the author

  • Rodrigo Lopes
  • Rodrigo LopesDevOps Engineer
Rodrigo is a DevOps engineer in the Wholesale & Rural Tech domain for the last 15 years. Rodrigo has been working with Java since version 1.0, with 20+ experience in the Java ecosystem. He has also gained more experience in the Azure world over the past few years.