Как тестировать специфический синтаксис базы данных в юнит тестах?
Что проверяют
Понимаете ли вы, где заканчивается юнит-тест. Правильный ответ почти парадоксальный: специфический SQL в юнит-тесте с моками не проверяется вовсе, и интервьюер ждёт, что вы это скажете. Следом спрашивают про H2 против Testcontainers и про скорость таких тестов.
Как отвечать
Разделите слои. Бизнес-логика тестируется на JUnit 5 и Mockito с замоканным репозиторием. А запрос с ON CONFLICT, jsonb, оконными функциями или LATERAL проверяется только настоящей базой: ошибку синтаксиса и семантики найдут лишь её парсер и планировщик.
Варианты по надёжности:
- мок
ConnectionилиJdbcTemplate: проверяет, что строка запроса совпала со строкой в тесте. Это тавтология, сам запрос может быть невалидным; - H2 в режиме совместимости (
MODE=PostgreSQL): быстро, но эмулирует лишь часть диалекта. Операторыjsonb, расширения вродеpg_trgmи многие функции не поддерживаются, поведение типов и сортировки отличается. Зелёный тест на H2 ничего не гарантирует для прода; - Testcontainers: поднимает в Docker ту же версию базы, что в проде, например образ
postgres:17. В Spring Boot 3.1 и новее контейнер подключается аннотацией@ServiceConnection, для слоя данных берут@DataJpaTestили@JdbcTestи следят, чтобы тестовый срез не подменил контейнер встроенной базой (@AutoConfigureTestDatabase(replace = Replace.NONE)).
Схему в контейнере накатывают теми же миграциями Flyway или Liquibase, что и на проде, иначе тестируется выдуманная схема. Данные готовятся в самом тесте, изоляцию даёт откат транзакции или очистка таблиц в @AfterEach.
Скорость решается одним контейнером на весь прогон (статическое поле в базовом классе). Проверяйте и граничные случаи: NULL, пустой массив, конфликт уникального ключа, часовые пояса в timestamptz.
Где спотыкаются
Мокают соединение с точной строкой SQL и называют это тестом запроса.
Верят H2. Запрос проходит в тестах и падает на первом деплое из-за диалекта.
Смешивают аннотации JUnit 4 (@Before, @After) с тестами JUnit 5. Такие методы молча не выполняются, данные не готовятся, и тест проверяет не то.