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-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.

Thank you for your efforts.