← Назад к вопросам

Какой контейнер поднимается при тестировании?

2.2 Middle🔥 171 комментариев
#Docker, Kubernetes и DevOps#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Контейнеры при тестировании в Java

Вопрос о контейнерах при тестировании относится к контейнеризации компонентов и инфраструктуры для тестирования. Это важная тема для разработчиков, работающих с микросервисами и интеграционными тестами.

TestContainers — основной инструмент

TestContainers — это популярная Java библиотека для запуска контейнеризированных зависимостей (БД, очереди, и т.д.) в тестах:

@SpringBootTest
@Testcontainers
public class UserRepositoryTest {
    
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
        .withDatabaseName("testdb")
        .withUsername("user")
        .withPassword("password");
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    void testFindUser() {
        User user = new User("test@example.com", "Test User");
        userRepository.save(user);
        
        User found = userRepository.findByEmail("test@example.com");
        assertThat(found).isNotNull();
    }
}

Типы контейнеров для тестирования

1. Database Containers (БД контейнеры)

PostgreSQL

@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
    .withDatabaseName("mydb")
    .withUsername("user")
    .withPassword("password")
    .withInitScript("init.sql");

MySQL

@Container
static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0")
    .withDatabaseName("testdb")
    .withUsername("root")
    .withPassword("password");

MongoDB

@Container
static MongoDBContainer mongo = new MongoDBContainer("mongo:6.0")
    .withExposedPorts(27017);

2. Message Queue Containers (очереди сообщений)

RabbitMQ

@Container
static RabbitMQContainer rabbitmq = new RabbitMQContainer("rabbitmq:3.12");

Kafka

@Container
static KafkaContainer kafka = new KafkaContainer(
    DockerImageName.parse("confluentinc/cp-kafka:7.5.0")
);

3. Other Service Containers (другие сервисы)

Redis

@Container
static GenericContainer<?> redis = new GenericContainer<>("redis:7")
    .withExposedPorts(6379);

Elasticsearch

@Container
static ElasticsearchContainer elasticsearch = 
    new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:8.0.0");

Docker API (кастомный контейнер)

@Container
static GenericContainer<?> custom = new GenericContainer<>("myimage:latest")
    .withExposedPorts(8080)
    .withEnv("ENV_VAR", "value")
    .waitingFor(Wait.forHttp("/health").forStatusCode(200));

Spring Boot Integration

С аннотациями @Testcontainers

@SpringBootTest
@Testcontainers
public class IntegrationTest {
    
    @Container
    static PostgreSQLContainer<?> db = new PostgreSQLContainer<>();
    
    @BeforeAll
    static void setup() {
        // db уже запущена
    }
}

С DynamicPropertySource

@SpringBootTest
@Testcontainers
public class DatabaseTest {
    
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>();
    
    @DynamicPropertySource
    static void registerDynamicProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }
}

Примеры полных тестов

Тест репозитория с Testcontainers

@SpringBootTest
@Testcontainers
public class OrderRepositoryTest {
    
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>()
        .withDatabaseName("testdb");
    
    @DynamicPropertySource
    static void setProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Test
    void testSaveAndFind() {
        Order order = new Order("ORD-001", BigDecimal.valueOf(100));
        
        Order saved = orderRepository.save(order);
        
        Optional<Order> found = orderRepository.findById(saved.getId());
        assertThat(found).isPresent();
        assertThat(found.get().getNumber()).isEqualTo("ORD-001");
    }
}

Тест с Kafka

@SpringBootTest
@Testcontainers
public class KafkaIntegrationTest {
    
    @Container
    static KafkaContainer kafka = new KafkaContainer(
        DockerImageName.parse("confluentinc/cp-kafka:7.5.0")
    );
    
    @DynamicPropertySource
    static void setProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.kafka.bootstrap-servers", kafka::getBootstrapServers);
    }
    
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    
    @Autowired
    private KafkaListener listener; // или @KafkaListener тест
    
    @Test
    void testProduceConsume() throws Exception {
        // Отправить сообщение
        kafkaTemplate.send("test-topic", "test-key", "test-message");
        
        // Проверить что слушатель получил
        // ...
    }
}

Docker Compose для сложной инфраструктуры

Для стека из нескольких сервисов можно использовать Docker Compose:

@SpringBootTest
@Testcontainers
public class DockerComposeTest {
    
    @Container
    static DockerComposeContainer<?> compose = 
        new DockerComposeContainer<>(new File("docker-compose.test.yml"))
            .withService("postgres")
            .withService("redis")
            .withService("kafka");
    
    @DynamicPropertySource
    static void properties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", 
            () -> "jdbc:postgresql://" + 
                  compose.getServiceHost("postgres", 5432) + ":" +
                  compose.getServicePort("postgres", 5432) + "/testdb");
    }
}

Best Practices

  1. Используй @Container для static полей — переиспользуется между тестами

    @Container
    static PostgreSQLContainer<?> db = new PostgreSQLContainer<>();
    
  2. Для isolate тестов используй instance контейнеры

    @Container
    PostgreSQLContainer<?> db = new PostgreSQLContainer<>(); // для каждого теста
    
  3. Добавь health checks

    .waitingFor(Wait.forLogMessage(".*ready to accept connections.*", 1))
    .waitingFor(Wait.forHttp("/health").forStatusCode(200))
    
  4. Минимизируй время запуска

    • Переиспользуй контейнеры (static)
    • Используй Ryuk для очистки
    • Настрой Docker оптимально
  5. Кэшируй образы

    docker pull postgres:15
    # Testcontainers будет переиспользовать
    

Gradle/Maven зависимости

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>1.19.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <version>1.19.3</version>
    <scope>test</scope>
</dependency>

Альтернативы

  • H2 In-Memory DB — для простых тестов
  • Embedded PostgreSQL — postgres-embedded
  • Mock Servers — WireMock, MockServer
  • Docker для CI/CD — GitHub Actions, GitLab CI

Итог: при тестировании Java приложений поднимаются контейнеры Testcontainers — PostgreSQL, MySQL, MongoDB, Redis, Kafka, RabbitMQ и другие. Это позволяет писать реальные интеграционные тесты без необходимости вручную управлять БД и сервисами.

Какой контейнер поднимается при тестировании? | PrepBro