TGViewer
Библиотека джависта | Java, Spring, Maven, Hibernate Библиотека джависта | Java, Spring, Maven, Hibernate @javaproglib · 22K subscribers
Post #7571 2.21K
☕️ Настройка Testcontainers + PostgreSQL

Надоели моки репозиториев, которые не ловят реальные SQL-баги?
Настраиваем Testcontainers, запускаем настоящий PostgreSQL прямо в тестах, без внешних зависимостей.

⚙️ Шаг 1 — Зависимости (Maven)

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.19.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.19.7</version>
<scope>test</scope>
</dependency>


> Для Gradle: testImplementation "org.testcontainers:postgresql:1.19.7"

🐳 Шаг 2 — Базовый тест

@SpringBootTest
@Testcontainers
class UserRepositoryTest {

@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16-alpine");

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

@Autowired
UserRepository userRepository;

@Test
void shouldSaveAndFindUser() {
var user = new User("alice@example.com");
userRepository.save(user);

var found = userRepository.findByEmail("alice@example.com");
assertThat(found).isPresent();
}
}


Всё. Spring подхватит datasource-проперти через @DynamicPropertySource — Liquibase/Flyway накатятся сами.

⚡️ Шаг 3 — Ускоряем: переиспользуем контейнер

По умолчанию контейнер поднимается на каждый тест-класс.
Чтобы один инстанс жил на весь прогон — выносим в абстрактный класс:

@SpringBootTest
@Testcontainers
public abstract class BaseIntegrationTest {

@Container
static final PostgreSQLContainer<?> POSTGRES =
new PostgreSQLContainer<>("postgres:16-alpine")
.withReuse(true); // ← ключевая строка

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


Наследуй в каждом интеграционном тесте — контейнер поднимется один раз.

🔍 Шаг 4 — Отладка: смотрим логи контейнера

POSTGRES.followOutput(new Slf4jLogConsumer(
LoggerFactory.getLogger("postgres-container")
));


Добавь до старта контейнера и все PostgreSQL логи пойдут в твой аппендер.

🔖 Сохраняй пост для следующего проекта.

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#Enterprise
  • ❤ 6
  • 👍 3
  • 🔥 1
  • 🤔 1
More from @javaproglib
  1. Oct 16, 2026🧩 Неизменяемый список всё ещё может измениться Collections.unmodifiableList() запрещает м…
  2. Oct 15, 2026💡 Logpoints: логи без правки кода и нового деплоя Чтобы увидеть значение переменной, необ…
  3. Oct 14, 2026Post #7897
  4. Oct 14, 2026Почему разработчик планирует отдавать больше задач Claude Винсент Шмальбах описал план пер…
  5. Oct 14, 2026🛠 Контейнер запущен, а тест всё равно падает Порт уже открыт, но приложение ещё применяет…
  6. Oct 13, 2026🧠 Почему BigDecimal считает 2.0 и 2.00 разными Что выведут эти две строки? var a = new Bi…
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 →