Ответ
Интеграционные тесты проверяют взаимодействие между компонентами системы (БД, API, внешние сервисы). Основной стек: Spring Boot Test с аннотациями @SpringBootTest, @DataJpaTest, @WebMvcTest. Для изоляции зависимостей использую Mockito, для тестовых данных — H2 (in-memory) или Testcontainers (реальные контейнеризированные БД).
Почему это важно: Интеграционные тесты выявляют проблемы, которые unit-тесты не ловят (например, некорректные маппинги JPA, конфигурацию Spring, работу транзакций).
Пример интеграционного теста для REST API:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void getUserById_ReturnsUserAndOkStatus() {
ResponseEntity<UserDto> response = restTemplate
.getForEntity("/api/users/1", UserDto.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getId()).isEqualTo(1L);
}
}
Ключевые практики:
- Изоляция тестов: Использую
@Transactionalили@DirtiesContextдля очистки состояния между тестами. - Тестовая БД: Для тестов с JPA применяю
@DataJpaTestс H2, для продакшен-подобного окружения — Testcontainers с PostgreSQL. - Слои тестирования: Тестирую не только контроллеры, но и сервисы с репозиториями, чтобы локализовать проблему.
Ответ 18+ 🔞
А, интеграционные тесты, говоришь? Ну это ж, блядь, самое интересное место, где вся архитектура твоя, такая умная, на поверку оказывается пиздопроебибной конструкцией из палок и соплей!
Смотри, в чём прикол. Ты там наюнитил свои сервисы, всё замокал, они у тебя летают как фанера над Парижем. А потом запускаешь это всё вместе, и тут, сука, начинается ёперный театр! JPA-маппинг, который ты неделю вылизывал, оказывается, нихуя не работает, потому что забыл @OneToMany(mappedBy = "..."). Или транзакции, блядь, ведут себя как последние шлюхи — откатываются там, где не надо, и коммитят там, где всё должно было сломаться.
Основной инструмент — это @SpringBootTest. Он, сука, поднимает почти весь контекст, как на продакшене. Ты ему говоришь: «Эй, дружок, дай-ка мне TestRestTemplate», а он тебе: «На, хули, проверяй свои контроллеры на вшивость».
Вот, глянь, пример, как это выглядит, когда ты пытаешься достучаться до своего же API:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void getUserById_ReturnsUserAndOkStatus() {
ResponseEntity<UserDto> response = restTemplate
.getForEntity("/api/users/1", UserDto.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getId()).isEqualTo(1L);
}
}
Выглядит-то просто, да? А теперь представь, что этот тест падает с 500 Internal Server Error. И начинается, блядь, детектив: то ли репозиторий хуйню отдаёт, то ли сервис словил NullPointer, то ли в контроллере маппинг кривой. Вот для этого они и нужны, эти тесты — чтобы выявить, где именно у тебя в цепочке сидит тот самый пидарас шерстяной, который всё ломает.
А теперь, блядь, главные правила, чтобы не охуеть от результатов:
-
Изоляция — наше всё. Один тест насрал в базу, другой пришёл — а там уже всё засрано. Красота? Нет, пиздец. Поэтому либо
@Transactionalв помощь (после теста всё откатывается, как будто ничего и не было), либо@DirtiesContext(перезагружаем весь контекст, медленно, но верно). Выбирай, в каком виде тебе больше нравится есть говно. -
База тестовая — голова спокойная. Для быстрых проверок JPA-маппингов и запросов —
@DataJpaTestи H2. Летит быстро, как хуй с горы. Но если хочешь почувствовать настоящую боль, как на проде (а ты должен её хотеть), то бери Testcontainers. Он поднимет тебе в докере реальную PostgreSQL, и ты узнаешь, что той красивой фичи, которая работала на H2, в постгресе не существует. И да, это спасёт тебе жопу перед выкаткой. -
Бей по всем слоям. Не зацикливайся только на контроллерах. Отдельно протестируй связку «Сервис -> Репозиторий». Уверен, что твой кастомный
@QueryсLEFT JOIN FETCHвозвращает ровно то, что надо? А вот нихуя! Интеграционный тест репозитория это быстро покажет. Так ты локализуешь проблему: не «всё падает», а «падает вот в этом конкретном методе репозитория, иди сюда и чини».
Короче, смысл в чём. Юнит-тесты — это проверка, что каждый винтик в твоём механизме вроде как крутится. А интеграционные — это когда ты собираешь весь этот механизм, пытаешься его завести, а он, блядь, взрывается у тебя в руках. И это овердохуища важный этап, чтобы не получить такой же взрыв на проде.