Подождите, пока контейнер не запустится в тестовых контейнерах с помощью GenericContainer для пользовательского образа PostgreSQL.

Я разрабатываю системные/интеграционные тесты на основе решения Testcontainers. Мне необходимо использовать образ нашей собственной базы данных PostgreSQL с уже примененной схемой базы данных.

По этой причине я использую Testcontainers GenericContainer.

private static final GenericContainer postgresDb = new GenericContainer(POSTGRES_IMAGE).withExposedPorts(5432);

Я разрабатываю тесты с помощью Spring Boot, поэтому я создал абстрактный класс, который будет содержать эту конфигурацию для всех тестов.

@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);
    
    }

}

Однако проблема в том, что когда тесты выполняются, контейнер все еще запускается. Это withStartupTimeout(Duration.ofSeconds(30)) по какой-то причине не работает.

Когда я останавливаюсь в методе отладки в свойствах и даю пару секунд для запуска контейнера, все тесты выполняются нормально.

Когда тесты терпят неудачу, я вижу следующий журнал:

org.postgresql.util.PSQLException: FATAL: the database system is starting up

Если я поставлю Thread.sleep(..), это тоже сработает, это не предпочтительное решение.

Каково правильное решение, чтобы подождать или правильная стратегия, чтобы знать, что контейнер готов?


person Bohdan Myslyvchuk    schedule 11.06.2021    source источник


Ответы (1)


Я думаю, что ответ находится в их документации, особенно в этой части:

Вывод журнала Стратегия ожидания

В некоторых ситуациях вывод журнала контейнера — это простой способ определить, готов он или нет. Например, мы можем дождаться сообщения «Готово» в журналах контейнера следующим образом:

public GenericContainer containerWithLogWait = new GenericContainer(DockerImageName.parse("redis:5.0.3"))
    .withExposedPorts(6379)
    .waitingFor(
        Wait.forLogMessage(".*Ready to accept connections.*\\n", 1)
    );

Примечание: вы захотите изменить сообщение на что-то вроде:

".*database system is ready to accept connections.*"

person Vincent C.    schedule 11.06.2021