Two issues are unclear in documentation
-
Probably outdated examples with
@TestcontainersEvery example contains@Testcontainersannotation. It seems be unnecessary. For example, Spring Initializer generates working test classes without the annotation. (If I'm right, I can create PR with@Testcontainersremoval) -
Two methods to register Container without explanation Container can be registered with
@org.testcontainers.junit.jupiter.Containerannotation 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.@Containeris 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
Testcontainersadd subsections describing the conventional methods for integrating the Testcontainers in Spring tests. - First method to be documented would be the vanilla method, using the
@Testcontainersannotation in combination with@SpringBootTestannotation. 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
@ImportTestContainersannotation 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.