Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Declare @Testcontainers before @SpringBootTest in documentation examples to ensure that Testcontainers is started before the application tries to use its containers #35572

Closed
sergey-morenets opened this issue May 19, 2023 · 6 comments
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@sergey-morenets
Copy link

sergey-morenets commented May 19, 2023

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

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 19, 2023
@wilkinsona
Copy link
Member

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 {

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label May 19, 2023
@sergey-morenets
Copy link
Author

sergey-morenets commented May 19, 2023

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?

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 19, 2023
@wilkinsona
Copy link
Member

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?

@wilkinsona wilkinsona added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels May 19, 2023
@sergey-morenets
Copy link
Author

sergey-morenets commented May 19, 2023

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.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 19, 2023
@wilkinsona
Copy link
Member

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.

@wilkinsona wilkinsona changed the title Caused by: java.lang.IllegalStateException: Mapped port can only be obtained after the container is started Declare @Testcontainers before @SpringBootTest in documentation examples to ensure that Testcontainers is started before the application tries to use its containers May 22, 2023
@wilkinsona wilkinsona added type: documentation A documentation update and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels May 22, 2023
@wilkinsona wilkinsona added this to the 3.1.x milestone May 22, 2023
@sergey-morenets
Copy link
Author

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.

@mhalbritter mhalbritter self-assigned this May 23, 2023
@mhalbritter mhalbritter modified the milestones: 3.1.x, 3.1.1 May 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

4 participants