Hi
I tried to use integration of Spring Boot & TestContainers added in Spring Boot 3.1.0. So I took this example from official Spring Boot documentation:
@SpringBootTest
@Testcontainers
class MyIntegrationTests {
@Container
@ServiceConnection
static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");
and create my test based on this template:
@SpringBootTest
@Testcontainers
public class OrderServiceTest {
@Container
@ServiceConnection
static GenericContainer<?> mysql = new MySQLContainer("mysql:8");
@Autowired
OrderService orderService;
@Test
void save_success() {
Order order = new Order();
orderService.save(order);
}
However I've got an exception running the test:
Caused by: java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
at org.testcontainers.shaded.com.google.common.base.Preconditions.checkState(Preconditions.java:174) ~[testcontainers-1.18.0.jar:1.18.0]
at org.testcontainers.containers.ContainerState.getMappedPort(ContainerState.java:161) ~[testcontainers-1.18.0.jar:1.18.0]
at org.testcontainers.containers.MySQLContainer.getJdbcUrl(MySQLContainer.java:104) ~[mysql-1.18.0.jar:1.18.0]
at org.springframework.boot.testcontainers.service.connection.jdbc.JdbcContainerConnectionDetailsFactory$JdbcContainerConnectionDetails.getJdbcUrl(JdbcContainerConnectionDetailsFactory.java:65) ~[spring-boot-testcontainers-3.1.0.jar:3.1.0]
at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:56) ~[spring-boot-autoconfigure-3.1.0.jar:3.1.0]
at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari.dataSource(DataSourceConfiguration.java:117) ~[spring-boot-autoconfigure-3.1.0.jar:3.1.0]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
Spring Boot: 3.1.0
Comment From: wilkinsona
The ordering of the @SpringBootTest and @Testcontainers annotations is important and the docs have got it wrong. @Testcontainers needs to go first so that the containers are started before the application under test is launched.
Can you please try the following and let us know if it works:
@Testcontainers
@SpringBootTest
public class OrderServiceTest {
Comment From: sergey-morenets
Hi @wilkinsona
Thank you for the quick response. Yes, you're correct. The following test configuration doesn't produce this error:
@Testcontainers
@SpringBootTest
public class OrderServiceTest {
Can you please update the documentation?
Comment From: wilkinsona
Thanks for trying the other order. What I wrote earlier was a bit too absolute as I've just reminded myself that the ordering doesn't always matter. I'd like to understand why it mattered in your case. To help with that, could you share a minimal sample that reproduces the problem you had with the "wrong" ordering?
Comment From: sergey-morenets
I just figured out what causes such behavior. It's that dependency:
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-database-spring-test</artifactId>
<version>2.3.0</version>
<scope>test</scope>
</dependency>
If I remove it then ordering doesn't matter.
Comment From: wilkinsona
Thanks, @sergey-morenets. I guess that embedded-database-spring-test is doing something in its integration that accesses the application context really early in the JUnit lifecycle, and crucially before Testcontainers' beforeAll callback is called to start the containers. I can't think of any scenario where it will be harmful to use @Testcontainers first and it'll be beneficial in situations like yours so let's update the docs to that effect.
Comment From: sergey-morenets
Thanks, @sergey-morenets. I guess that
embedded-database-spring-testis doing something in its integration that accesses the application context really early in the JUnit lifecycle, and crucially before Testcontainers'beforeAllcallback is called to start the containers. I can't think of any scenario where it will be harmful to use@Testcontainersfirst and it'll be beneficial in situations like yours so let's update the docs to that effect.
Thank you for your efforts.