Код-ревью Middle Тестирование в Spring обновлено

Код-ревью: интеграционный тест заказов

Вопрос

Найдите проблемы в тесте.

@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@AutoConfigureTestDatabase
class OrderServiceTest {
    @Autowired OrderService service;
    @Autowired OrderRepository repo;
    @MockitoBean MailSender mail;

    @Test
    void createsOrder() throws Exception {
        service.create(new CreateOrder("anna@example.com", 500));
        Thread.sleep(3000);
        assertEquals(1, repo.count());
    }

    @Test
    void calculatesDiscount() {
        assertEquals(450, service.discounted(500, 10));
    }

    @Test
    void sendsMail() {
        service.create(new CreateOrder("anna@example.com", 500));
        verify(mail).send(any(), any());
    }
}

Коротко

Правильно разделить: логику скидок покрыть юнит-тестом без Spring, сохранение заказа проверить @DataJpaTest или @SpringBootTest с Testcontainers и очисткой данных, асинхронные эффекты ждать через Awaitility, а @DirtiesContext убрать.

Что должен найти ревьюер

  1. Производительностьстрока 1
    Полный @SpringBootTest для проверки логики сервиса: можно юнит-тестом с моками, а для слоя данных взять @DataJpaTest.
  2. Производительностьстрока 2
    @DirtiesContext после каждого метода пересоздаёт весь контекст: тест идёт минуты.
  3. Ошибкастрока 3
    @AutoConfigureTestDatabase подменяет базу встроенной H2: native-запросы и особенности PostgreSQL не проверяются. Нужен Testcontainers.
  4. Ошибкастрока 12
    Thread.sleep(3000) вместо ожидания условия: тест медленный и всё равно может мигать на медленном CI.
  5. Ошибкастрока 13
    Проверка repo.count() == 1 держится только на том, что @DirtiesContext каждый раз даёт пустую базу. Стоит убрать его ради скорости, и тест начнёт зависеть от sendsMail и порядка запуска. Нужна явная очистка данных или проверка конкретного заказа.
  6. Стильстрока 17
    Чистая арифметика скидки проверяется с поднятием всего контекста: это юнит-тест.

Разбор

Правильно разделить: логику скидок покрыть юнит-тестом без Spring, сохранение заказа проверить @DataJpaTest или @SpringBootTest с Testcontainers и очисткой данных, асинхронные эффекты ждать через Awaitility, а @DirtiesContext убрать.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.