Francislainy Campos
Francislainy Campos

Reputation: 4164

Mapped port can only be obtained after the container is started - Testcontainers with @ServiceConnection and Spring 3.1.4

I'm trying to update my tests to use the latest support for Spring 3.1.4 for testcontainers, which replaces the @DynamicSource annotation with @ServiceConnection as per here . However, I'm getting this error:

Caused by: org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: 
Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: 
Factory method 'dataSource' threw exception with message: 
Mapped port can only be obtained after the container is started

These are my dependencies:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-testcontainers</artifactId>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.testcontainers</groupId>
   <artifactId>junit-jupiter</artifactId>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.testcontainers</groupId>
   <artifactId>postgresql</artifactId>
   <scope>test</scope>
</dependency>

And here my classes:


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class FollowshipIT extends BasePostgresConfig {

    @LocalServerPort
    private int port;

    ...

}

public class BasePostgresConfig {

    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:13.5");

}

I tried both with and without keeping an active profile and -test.yml file with DB configs like the one below and annotating my BasePostgresConfig class with @ActiveProfiles("test"), as I had before for my previous configuration, but that didn't work either.

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
    url: jdbc:tc:postgresql:13.5:///helloTalk

Here is the full code for my application.

Thank you.

Upvotes: 1

Views: 2461

Answers (2)

Francislainy Campos
Francislainy Campos

Reputation: 4164

This works:

@Testcontainers
public class BasePostgresConfig {

    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres;

    static {
        postgres = new PostgreSQLContainer<>("postgres:13.5");
        postgres.start();
    }

}

Perhaps there could be other ways to achieve this, but for this solution I had to start the container in a static block by calling postgres.start().

About the @TestContainers annotation, the tests pass also without it, but better to leave it there so the containers are closed after the test execution.

UPDATE

After some further investigation, I've noticed the need to call postgres.start() seems to be related to the fact the tests have the @TestInstance(Lifecycle.PER_CLASS) annotation, which is used to remove the need for the @BeforeAll method to be static.

Upvotes: -1

Edd&#250; Mel&#233;ndez
Edd&#250; Mel&#233;ndez

Reputation: 6530

you are missing @Testcontainers annotation at test class level, which will start and stop container implementations annotated with @Container

You can check the Testcontainers JUnit 5 docs https://java.testcontainers.org/quickstart/junit_5_quickstart/

In order to know more about Testcontainers and JUnit 5 integration see https://testcontainers.com/guides/testcontainers-container-lifecycle/

Also, take into account that the following code is not needed

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
    url: jdbc:tc:postgresql:13.5:///helloTalk

due to PostgreSQLContainer is being used directly. Check more here

Upvotes: 1

Related Questions