Java Academy · Урок

Testcontainers: интеграционные тесты с реальной базой данных

Запускайте PostgreSQL в Docker с помощью Testcontainers и выполняйте интеграционные тесты против реальной базы данных.

Урок 4 из 413 шагов

«Testcontainers: интеграционные тесты с реальной базой данных» — бесплатный урок Java Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Зачем нужны Testcontainers?

Базы данных H2 в памяти не поддерживают специфичные для PostgreSQL возможности (JSON, полнотекстовый поиск, ON CONFLICT). Testcontainers запускает настоящие контейнеры Docker во время тестов, предоставляя базу данных, идентичную производственной.

Добавление зависимости Testcontainers

Добавьте BOM Testcontainers и модуль PostgreSQL в файл сборки. Spring Boot 3.1+ включает управляемую версию Testcontainers.

// build.gradle:
testImplementation "org.testcontainers:junit-jupiter"
testImplementation "org.testcontainers:postgresql"
// Optionally use Spring Boot Testcontainers support:
testImplementation "org.springframework.boot:spring-boot-testcontainers"

@Testcontainers и @Container

Пометьте класс теста аннотацией @Testcontainers и объявите контейнер как статическое поле @Container. JUnit 5 запустит и остановит его автоматически.

@Testcontainers
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryIntegrationTest {
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
        .withDatabaseName("testdb")
        .withUsername("test")
        .withPassword("test");
}

Настройка DataSource из контейнера

Используйте @DynamicPropertySource, чтобы передать динамический порт контейнера и учетные данные в конфигурацию DataSource Spring.

@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
    registry.add("spring.datasource.url",      postgres::getJdbcUrl);
    registry.add("spring.datasource.username", postgres::getUsername);
    registry.add("spring.datasource.password", postgres::getPassword);
}

Spring Boot 3.1 ServiceConnection

Spring Boot 3.1+ автоматически настраивает DataSource из компонента Testcontainers, аннотированного с помощью @Container и @ServiceConnection, поэтому @DynamicPropertySource не требуется.

@Bean
@ServiceConnection
static PostgreSQLContainer<?> postgresContainer() {
    return new PostgreSQLContainer<>("postgres:16-alpine");
}

Паттерн общего контейнера

Запуск контейнера для каждого класса тестов выполняется медленно. Используйте одно статическое поле с Startables.deepStart() или абстрактный базовый класс, чтобы использовать один контейнер во всех тестах.

abstract class AbstractIntegrationTest {
    @Container
    static final PostgreSQLContainer<?> POSTGRES =
        new PostgreSQLContainer<>("postgres:16-alpine").withReuse(true);
    static { POSTGRES.start(); }
    @DynamicPropertySource
    static void props(DynamicPropertyRegistry r) {
        r.add("spring.datasource.url",      POSTGRES::getJdbcUrl);
        r.add("spring.datasource.username", POSTGRES::getUsername);
        r.add("spring.datasource.password", POSTGRES::getPassword);
    }
}

Тестирование функций PostgreSQL

С помощью Testcontainers можно тестировать столбцы JSON, операторы JSONB, полнотекстовый поиск и ON CONFLICT DO UPDATE — возможности, которых нет в H2.

@Test
void jsonb_search_works() {
    // Insert row with JSONB column, then query
    List<Event> logins = repo.findByType("login");
    assertEquals(1, logins.size());
}

Несколько контейнеров: Compose

Используйте DockerComposeContainer, чтобы запускать полный стек (PostgreSQL + Redis + Kafka) для интеграционных тестов, которым требуются несколько сервисов.

@Container
static DockerComposeContainer<?> compose = new DockerComposeContainer<>(
    new File("src/test/resources/docker-compose.yml"))
    .withExposedService("postgres", 5432)
    .withExposedService("redis", 6379);

Ryuk: автоматическая очистка

Testcontainers использует контейнер Ryuk, чтобы автоматически останавливать и удалять контейнеры при завершении работы JVM — даже если тест завершился с ошибкой, предотвращая накопление неиспользуемых контейнеров.

@SpringBootTest с Testcontainers

Используйте @SpringBootTest вместо @DataJpaTest, чтобы тестировать весь стек приложения (контроллеры, сервисы, репозитории) с настоящим контейнером PostgreSQL.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
class FullIntegrationTest extends AbstractIntegrationTest {
    @LocalServerPort int port;
    @Autowired TestRestTemplate rest;
    @Test
    void end_to_end_user_creation() {
        ResponseEntity<UserDto> r = rest.postForEntity("/api/users", createReq(), UserDto.class);
        assertEquals(HttpStatus.CREATED, r.getStatusCode());
    }
}

Кэширование образов контейнеров

Testcontainers кэширует загруженные образы Docker локально. Загружайте образы в CI до запуска тестов (docker pull postgres:16-alpine), чтобы не тратить время на загрузку во время выполнения тестов.

Быстрая проверка

Какая аннотация автоматически подключает контейнер Testcontainers к DataSource Spring в Spring Boot 3.1+?

Итоги

Testcontainers запускает настоящие контейнеры Docker для интеграционных тестов. Используйте @Container + @DynamicPropertySource или @ServiceConnection (Boot 3.1+). Используйте общие контейнеры во всех тестах с помощью паттерна единственного контейнера. Тестируйте специфичные для PostgreSQL функции, которых нет в H2.

Можно начать бесплатно

Изучай Java с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
104
Уроки
374

Часто задаваемые вопросы

Урок «Testcontainers: интеграционные тесты с реальной базой данных» бесплатный?

Да — полный текст урока «Testcontainers: интеграционные тесты с реальной базой данных» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Testcontainers: интеграционные тесты с реальной базой данных»?

Запускайте PostgreSQL в Docker с помощью Testcontainers и выполняйте интеграционные тесты против реальной базы данных. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Testcontainers: интеграционные тесты с реальной базой данных»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Параметризованные тесты с @CsvSource и @MethodSource
  2. Mockito: продвинутые возможности — перехватчики аргументов и шпионы
  3. Срезы тестирования Spring Boot: @WebMvcTest и @DataJpaTest
  4. Testcontainers: интеграционные тесты с реальной базой данных
← Назад к Java Academy