Для чего используется аннотация @SpringBootTest и в каких сценариях?

Ответ

@SpringBootTest — это основная аннотация для интеграционного тестирования Spring Boot приложений. Она загружает полный контекст приложения, имитируя его реальный запуск.

Основное назначение:

  • Тестирование взаимодействия нескольких компонентов (сервисов, репозиториев).
  • Тестирование с доступом к реальной или in-memory базе данных.
  • Тестирование REST API с поднятым embedded-сервером.

Пример базового теста:

@SpringBootTest
class UserServiceIntegrationTest {
    @Autowired
    private UserService userService;

    @Test
    void shouldCreateAndFindUser() {
        User newUser = userService.create("test@email.com");
        User foundUser = userService.findById(newUser.getId());

        assertThat(foundUser.getEmail()).isEqualTo("test@email.com");
    }
}

Настройка окружения:

@SpringBootTest(
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT // Запуск на случайном порту
)
class MyControllerTest {
    @LocalServerPort
    private int port;

    @Test
    void testEndpoint() {
        // Тестирование через TestRestTemplate или WebTestClient
    }
}
Сравнение с другими аннотациями: Аннотация Назначение Контекст Скорость
@SpringBootTest Полная интеграция Полный контекст Медленно
@WebMvcTest Тестирование MVC-слоя Только веб-слой Быстро
@DataJpaTest Тестирование JPA Только JPA и БД Быстро
@JsonTest Тестирование JSON Только Jackson Очень быстро

Рекомендации:

  1. Используйте @SpringBootTest для сквозных (end-to-end) тестов.
  2. Для изолированных unit-тестов предпочитайте @WebMvcTest, @DataJpaTest или обычные тесты без Spring.
  3. Используйте @MockBean для замены тяжелых зависимостей (например, внешних сервисов).
  4. Настройте @TestConfiguration для предоставления тестовых бинов.

Ответ 18+ 🔞

Давайте разберём эту вашу аннотацию @SpringBootTest, а то некоторые думают, что это такая волшебная палочка, которую можно тыкать куда попало. Нет, блядь, это не для всего подряд!

Представьте, что вы хотите проверить, работает ли ваш новый автомобиль. Вы же не будете для этого сразу на трассу выезжать и в полный газ давить? Сначала фары моргнёте, стеклоочистители, сигнал — это unit-тесты, изолированные проверки. А @SpringBootTest — это как раз ваша полноценная поездка по трассе, со всеми светофорами, бензобаком и этим вот, блядь, подшипником в левом переднем колесе. Загружается весь контекст приложения, как будто вы его запустили по-настоящему. Тяжело, медленно, но зато реалистично, ёпта.

Зачем это реально нужно, а не просто по приколу?

  • Когда вам надо удостовериться, что ваш сервис не поссорился с репозиторием и они вместе дружно тащат данные из базы. Интеграция, сука!
  • Когда нужно протестировать REST-контроллер, чтобы он не просто тупой метод вызывал, а именно через embedded-сервер (типа Tomcat) принимал HTTP-запросы и отдавал ответы. Полный цикл, блядь.
  • Когда вы сомневаетесь, что ваша конфигурация, на которую вы потратили три часа, вообще рабочая. Вот тут @SpringBootTest её поднимет и покажет, где вы накосячили.

Вот вам простейший пример, с которого многие начинают:

@SpringBootTest
class UserServiceIntegrationTest {
    @Autowired
    private UserService userService; // Контекст поднят, бин внедрился

    @Test
    void shouldCreateAndFindUser() {
        User newUser = userService.create("test@email.com");
        User foundUser = userService.findById(newUser.getId());

        assertThat(foundUser.getEmail()).isEqualTo("test@email.com"); // И всё это с реальной или тестовой БД!
    }
}

А если вам нужен именно веб-сервер для тестов API? Пожалуйста, настройте окружение:

@SpringBootTest(
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT // Чтоб порты не конфликтовали, как бабы у подъезда
)
class MyControllerTest {
    @LocalServerPort
    private int port; // Сюда Spring воткнёт номер того самого случайного порта

    @Test
    void testEndpoint() {
        // А тут уже можно TestRestTemplate или WebTestClient взять и на этот порт запросы слать
    }
}

Теперь самое важное — не путать с другими аннотациями, а то будете как дураки тесты по полчаса ждать!

Аннотация Для чего создана Что поднимает Скорость
@SpringBootTest Полноценная интеграция, сквозные тесты Весь контекст, всю вашу малину Овердохуища медленно
@WebMvcTest Проверить, не гонит ли чушь ваш контроллер Только веб-слой, всё остальное замокано Достаточно быстро
@DataJpaTest Убедиться, что запросы в БД не хуйню возвращают Контекст JPA и базу данных (часто H2) Быстро
@JsonTest Проверить, как ваши объекты в JSON превращаются и обратно Только Jackson (библиотеку для JSON) Очень быстро, чих-пых и готово

Итоговые рекомендации, чтобы не быть мудем:

  1. Тащите @SpringBootTest для больших, жирных end-to-end тестов, где нужно проверить всё от контроллера до базы. Для всего остального — есть более лёгкие инструменты.
  2. Для тестирования одной конкретной хуйни (например, логики в сервисе) — используйте обычные unit-тесты без Spring вообще. Замокали зависимости через Mockito и поехали.
  3. Если в интеграционном тесте у вас тормозит какая-то внешняя зависимость (например, платёжный шлюз), подмените её на @MockBean. Скажите Spring: "Не грузи эту тяжелую хуйню, вот тебе муляж".
  4. Нужны особые бины только для тестов? Создайте внутренний статический класс с аннотацией @TestConfiguration и настройте там что душе угодно.

Короче, думайте головой, что вы тестируете. Не надо из пушки по воробьям палить — ресурсы жалко, да и время, блядь, своё.