Зависимые тесты (Test Interdependency)

Тест явно рассчитывает на то, что другой тест уже выполнился и оставил систему в нужном состоянии. Зависимость закреплена через @Order или просто предполагается по алфавитному порядку.

Симптомы

  • Использование @TestMethodOrder(MethodOrderer.OrderAnnotation.class) с @Order
  • Тест-метод не создаёт свои данные, а использует объекты, созданные в @BeforeAll предыдущего теста
  • «Тест 2 нельзя запустить без теста 1»
  • При запуске подмножества тестов — NullPointerException или EntityNotFoundException
  • Комментарии вида // предполагаем, что createUser уже выполнился

Причины возникновения

  • Попытка избежать повторения кода (создания данных) через цепочку тестов
  • Перенос стиля интеграционных скриптов (шаг 1 → шаг 2 → шаг 3) в unit/e2e тесты
  • Незнание о @BeforeEach и фабричных методах как альтернативах
  • Экономия времени прогона: «зачем создавать пользователя дважды?»

Почему это проблема

  • Каскадные падения: сломался тест 1 → упали тесты 2, 3, 4, ... — непонятно, где реальный дефект
  • Нельзя запустить в одиночку: CI-конфигурация run only failed tests не работает
  • Нельзя параллелизировать: JUnit может запускать тесты в любом порядке в разных потоках
  • Ложная зависимость: тест 2 «тестирует» логику теста 1, а не систему

Решение

Каждый тест самодостаточен — создаёт всё необходимое в своём теле или @BeforeEach:

// ❌
@Test @Order(2)
void deleteUser() {
    userService.delete("ivan@test.com"); // кто создал этого пользователя?
}

// ✅
@Test
void deleteUser() {
    userService.create("ivan@test.com"); // создаём сами
    userService.delete("ivan@test.com");
    assertFalse(userService.exists("ivan@test.com"));
}