Two issues are unclear in documentation

  1. Probably outdated examples with @Testcontainers Every example contains @Testcontainers annotation. It seems be unnecessary. For example, Spring Initializer generates working test classes without the annotation. (If I'm right, I can create PR with @Testcontainers removal)

  2. Two methods to register Container without explanation Container can be registered with @org.testcontainers.junit.jupiter.Container annotation or as a Spring @Bean. Which one is better for which case? On one hand, Spring Initializer generates @Bean, so it looks as recommended. On the other hand, Spring Boot Reference begins with @Container, to it looks as primary decision hint. @Container is a bit boilerplate-less, so the hint looks reasonable. As a developer, which method should I choose at the beginning? (ref: https://docs.spring.io/spring-boot/reference/testing/testcontainers.html)

Comment From: snicoll

For example, Spring Initializer generates working test classes without the annotation. (If I'm right, I can create PR with @Testcontainers removal

That's not the same thing. In the case you've described, the containers are created as beans and our integration takes over. If you create them using field on the test class itself, @Testcontainers is required to handle the lifecycle.

On one hand, Spring Initializer generates @Bean, so it looks as recommended.

That's quite a shortcut. Spring Initializr uses this mean because the containers are reused (see the test main class). If. you don't need them to be reused, then there's no need for the extra class.

Which one is better for which case?

If you need to reuse them, put them in a place where they can be. Otherwise don't. I think the section of the doc you've shared is just fine, it's teaching you how the Spring Boot support augments what Testcontainers does itself.

With all that said, I believe that a dedicated sub-section about the bean method use case could be warranted there. We talk about @Bean method for the purpose of identifying the container but it feels like we could give it some sort of introduction.

Comment From: wilkinsona

There's some existing information about the @Bean-based approach in the section on using Testcontainers at development time.

Comment From: michaldo

If you create them using field on the test class itself, @Testcontainers is required to handle the lifecycle.

I created project with Spring Initializr with the following URL

https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.4.1&packaging=jar&jvmVersion=21&groupId=me&artifactId=me&name=me&description=Demo%20project%20for%20Spring%20Boot&packageName=me.me&dependencies=data-mongodb,testcontainers

Then I added the following test:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;

@SpringBootTest class MyTest {

    @Container
    @ServiceConnection
    static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:latest");

    @Test void hello() {
        System.out.println(mongoDBContainer.getContainerInfo().getState());
    }
}

and output is

InspectContainerResponse.ContainerState(status=running, running=true, paused=false, restarting=false, oomKilled=false, dead=false, pid=19058, exitCode=0, error=, startedAt=2025-01-09T10:56:06.545529148Z, finishedAt=0001-01-01T00:00:00Z, health=null)

Thats why I think @Testcontainers is outdated

Comment From: michaldo

I think the section of the doc you've shared is just fine, it's teaching you how the Spring Boot support augments what Testcontainers does itself.

I feel technical details are explained but "Big Picture" is missing. My understanding of "Big Picture" is the following:

No-brainer one docker container should be used in integration test. Let's assume 2 test files want use and share docker container. I know 3 ways to sharing among test files 1. Common base class 2. Shared Spring Configuration 3. BeforeAllCallback

If 2 test files share the same Spring context, any option will ensure exactly-once-container. (2) looks as prefered because is simpler than (3), more flexible than (1) and reusable by "Using Testcontainers at Development Time" If 2 test files use different Spring contexts, (2) is not correct because 2 containers are instantiated. (1) or (3) must be choosen, trade-off simplicity against flexibility

Update

I eventually read about @ImportTestcontainers in https://docs.spring.io/spring-boot/reference/features/dev-services.html#features.dev-services.testcontainers.at-development-time.importing-container-declarations. It is 4th way to share container among test files. 1. Does not need common base class 2. Multiple contexts - one container 3. Does not need manual code like BeforeAllCallback implementation

It seems to me that @ImportTestcontainers is a winner: optimal for any scenario, except single class test

Comment From: thecooldrop

I would like to work on this issue

Comment From: snicoll

Thanks for the offer @thecooldrop but I disagree with the analysis of @michaldo so we'll have to figure out what we want to document.

Comment From: thecooldrop

Hello @snicoll , thanks for the prompt answer. In general I can see your point. In my view the usage of @Testcontainers annotation is not outdated, but is only one of the ways in which Testcontainers can be integrated with Spring tests.

Independently of what gets decided I would propose following addition to testcontainers reference page:

  • Directly after section Testcontainers add subsections describing the conventional methods for integrating the Testcontainers in Spring tests.
  • First method to be documented would be the vanilla method, using the @Testcontainers annotation in combination with @SpringBootTest annotation. This section can contain a reference to official Testcontainers JUnit5 documentation for more details. It would need to be noted that in this case it is the Testcontainers framework which is managing the lifecycle of containers and not Spring Boot.
  • Second method is the usage of beans managed by Spring. Here a configuration class together with explanation of the lifecycle would be necessary. Current documentation does not clarify if/when test containers are reused across test methods and test classes when containers are configured as beans.
  • Third method is usage of @ImportTestContainers annotation as described in usage of testcontainers at development time. The site on usage of test containers at development time could then be adapted to be more succint and to link to the reference site instead of repeating the details.

I will stop the work on the issue, until you give a green light.

Comment From: snicoll

Thats why I think @Testcontainers is outdated

Unfortunately, that's not accurate. You "could" remove @Testcontainers in some cases that hardly makes it robust: the container must be annotated with @ServiceConnection and you must not interact with the container until someone's used the connection details.

As such the use of @Testcontainers in the current example is valid: the start() that happens as a result of some of the connection details being accessed is really intended as an insurance policy to make sure that the container's been started. It isn't intended to be the primary way of starting it.

@thecooldrop I cannot guarantee that we would go with that plan but that looks quite compelling. Would you like to submit a PR with your work?

Comment From: thecooldrop

Hi @snicoll, yes I would love to start contributing to the project. One warning though: I will not be able to get to it before the weekend. If that is acceptable please do assign this to me.

Comment From: thecooldrop

Hello @snicoll I have proposed a change in PR. I was not able to build the Antora documentation locally, but noted that I got errors in build even for code that was there before my changes. I am looking forward to having the doc changes reviewed.