I'm developing system/integration tests based on Testcontainers solution. It is required for me to use our own database PostgreSQL image with already applied database schema.
For this reason I'm using Testcontainers GenericContainer.
private static final GenericContainer postgresDb = new GenericContainer(POSTGRES_IMAGE).withExposedPorts(5432);
I'm developing tests with Spring Boot, so for this reason I've created abstract class which will hold this config for all tests
@ActiveProfiles("test")
@SpringBootTest
public abstract class AbstractTests {
private static final DockerImageName POSTGRES_IMAGE = DockerImageName.parse("docker-name:latest");
private static final GenericContainer postgresDb;
static {
postgresDb = new GenericContainer(POSTGRES_IMAGE)
.withExposedPorts(5432);
postgresDb.withStartupTimeout(Duration.ofSeconds(30))
.start();
}
@DynamicPropertySource
static void properties(DynamicPropertyRegistry registry) throws InterruptedException {
final String s = "jdbc:postgresql://"+ postgresDb.getHost() +":"+ postgresDb.getMappedPort(5432) + "/test";
registry.add("spring.datasource.url", () ->s);
}
}
However, the problem is that when when tests are running, container still is starting. This withStartupTimeout(Duration.ofSeconds(30)) doesn't for work some reason.
When I stop in debug at properties method and give a couple of seconds to start a container all tests run fine.
When tests fail I see next log:
org.postgresql.util.PSQLException: FATAL: the database system is starting up
If I put Thread.sleep(..) it also works, it is not preferable solution.
What is the right solution to wait or right strategy to know that container is ready?
I think the answer is in their documentation, particularly this part:
Log output Wait Strategy
In some situations a container's log output is a simple way to determine if it is ready or not. For example, we can wait for a `Ready' message in the container's logs as follows:
public GenericContainer containerWithLogWait = new GenericContainer(DockerImageName.parse("redis:5.0.3")) .withExposedPorts(6379) .waitingFor( Wait.forLogMessage(".*Ready to accept connections.*\\n", 1) );
Note: you will want to change the message to something like:
".*database system is ready to accept connections.*"