TGViewer
Java Geek Java Geek @java_geek · 2.37K subscribers
Post #523 258
🐳 Java Testing: Хватит мокать базы данных!

Вы всё еще используете H2 для тестов, а в продакшене стоит PostgreSQL? Или, может быть, вы поднимаете docker-compose руками перед запуском mvn test?


⛔ Как было раньше

Раньше нам приходилось делать трюки с @DynamicPropertySource, чтобы вручную прокинуть jdbc:url, username и password из поднятого контейнера в контекст Spring.


// Old School (Java 17 / Boot 2.7)
@DynamicPropertySource
static void registerPgProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
// ... куча ручного кода
}



✅ Как сейчас

@ServiceConnection сама понимает, что это за контейнер (Postgres, Redis, Kafka, RabbitMQ), и автоматически прописывает нужные свойства в ваш application.properties на время теста.


@Testcontainers
@SpringBootTest
class OrderIntegrationTest {

// 1. Объявляем контейнер
@Container
@ServiceConnection // 👈 Вся магия тут!
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16-alpine");

@Autowired
private OrderRepository repository;

@Test
void shouldSaveOrder() {
// 2. Тест работает с РЕАЛЬНОЙ базой в Docker
var order = new Order("item-123", BigDecimal.TEN);
repository.save(order);

assertThat(repository.findAll()).hasSize(1);
}
}




Писать контейнер в каждом тестовом классе - дурной тон (и медленно, так как Docker будет стартовать каждый раз заново).
В Spring Boot 3.1 появился паттерн TestConfiguration, который позволяет переиспользовать контейнеры.

Создаем один файл конфигурации:


@TestConfiguration(proxyBeanMethods = false)
public class ContainersConfig {

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

@Bean
@ServiceConnection
public KafkaContainer kafkaContainer() {
return new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.4.0"));
}
}



Теперь в любом тесте просто импортируем этот конфиг:


@Import(ContainersConfig.class)
@SpringBootTest
class AnyIntegrationTest { ... }




Вы можете использовать этот же конфиг, чтобы запустить само приложение локально с поднятыми контейнерами! Больше не нужно настраивать локальный Postgres.

В папке src/test/java создайте класс для запуска:


public class TestApplication {
public static void main(String[] args) {
SpringApplication.from(MyRealApplication::main)
.with(ContainersConfig.class) // Подключаем наши контейнеры
.run(args);
}
}



Запускаете TestApplication -> Spring сам поднимает Docker-контейнеры -> приложение коннектится к ним -> вы работаете.

🏁 Итог

• Изоляция: Каждый прогон тестов - чистая среда.
• Честность: Тестируйте на том, что будет в продакшене.
• Удобство: @ServiceConnection убрал весь бойлерплейт.

#SpringTest #Testcontainers #Java #DevOps #Docker

📲 Мы в MAX

👉 @java_geek
  • 👍 2
More from @java_geek
  1. Sep 24, 2026Что такое стек-трейс? Стек-трейс (stack trace) представляет собой список вызовов методов в…
  2. Sep 17, 2026Как перебрать элементы LinkedList в обратном порядке, не используя медленный get(index)? Д…
  3. Sep 15, 2026Array vs ArrayList Выбор между Array (стандартным Java-массивом) и ArrayList зависит от сп…
  4. Sep 11, 2026Какова цель ключевого слова final, когда оно используется с переменной? Ключевое слово fin…
  5. Sep 9, 2026☕ Java Tip: Как работает var в Java С версии Java 10 появился ключевое слово var. Оно упро…
  6. Sep 7, 2026Что такое перегрузка методов в Java? Перегрузка методов — это мощный приём, который позвол…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →