JavaRush /Курси /Модуль 5. Spring /Підтримка тестування в Spring Boot

Підтримка тестування в Spring Boot

Модуль 5. Spring
Рівень 4 , Лекція 9
Відкрита

Давайте почнемо з самого початку. Навіщо взагалі потрібне тестування? Ви ж не хочете, щоб ваші користувачі натрапили на баги в продакшені, правда? Тестування дозволяє знаходити й усувати проблеми ще до того, як вони завдадуть шкоди вашому застосунку або вашій репутації. А Spring Boot пропонує зручні інструменти, щоб спростити це завдання.

Spring Boot інтегрується з такими популярними бібліотеками для тестування, як JUnit і TestNG, і надає додаткові можливості через spring-boot-starter-test. Цей starter включає все необхідне для написання тестів:

  • JUnit 5 для написання тестів.
  • AssertJ для лаконічних перевірок умов.
  • Hamcrest для потужних і наочних виразів.
  • Mockito для створення заглушок (mock-об'єктів).
  • Spring Test — спеціальний модуль Spring, який допомагає тестувати застосунки в контексті Spring.

Налаштування тестового середовища

Спочатку переконайтесь, що в вашому pom.xml або build.gradle є залежність на spring-boot-starter-test.


<!-- pom.xml -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

Основи Spring Boot Test

Разом із spring-boot-starter-test ми отримуємо потужний механізм для тестування компонентів Spring‑застосунків: контролерів, сервісів, репозиторіїв і навіть усієї системи загалом.

Анотації Spring Boot Test

  • @SpringBootTest — запускає весь контекст застосунку для проведення інтеграційних тестів.
  • @MockBean — створює тестові (mock) версії бінів. Корисно для ізоляції тестованої логіки.
  • @WebMvcTest — піднімає тільки контекст Spring MVC, зручно для тестування REST-контролерів.
  • @DataJpaTest — створює контекст для тестування репозиторіїв і роботи з JPA.

Приклад: припустимо, у нас є метод в сервісі, який повертає список користувачів. Використовуючи анотації, ми можемо протестувати його логіку.


// UserService.java
@Service
public class UserService {
    public List<String> getUsers() {
        return Arrays.asList("Alice", "Bob", "Charlie");
    }
}


// UserServiceTest.java
@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void testGetUsers() {
        List<String> users = userService.getUsers();
        assertEquals(3, users.size());
        assertTrue(users.contains("Alice"));
    }
}

Практика тестування

Давайте тепер подивимось, як можна протестувати різні частини нашого застосунку.

Тестування REST-контролерів

Типовий контролер:


// UserController.java
@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping
    public List<String> getUsers() {
        return List.of("Alice", "Bob", "Charlie");
    }
}

Тестуємо за допомогою @WebMvcTest:


@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testGetUsers() throws Exception {
        mockMvc.perform(get("/users"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$[0]").value("Alice"))
                .andExpect(jsonPath("$[1]").value("Bob"));
    }
}

Що тут відбувається?

  • Ми використовуємо MockMvc для виконання HTTP-запитів до нашого контролера.
  • Метод perform() відправляє GET-запит на /users.
  • За допомогою andExpect() перевіряємо статус відповіді й вміст JSON-масиву.

Тестування репозиторіїв

Покажу приклад з використанням JPA. Пишемо репозиторій для керування сутністю User.

Сутність:


// User.java
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // getters & setters
}

Репозиторій:


// UserRepository.java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
}

Тест репозиторію:


@DataJpaTest
public class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void testFindByName() {
        // Arrange
        User user = new User();
        user.setName("Alice");
        userRepository.save(user);

        // Act
        List<User> users = userRepository.findByName("Alice");

        // Assert
        assertEquals(1, users.size());
        assertEquals("Alice", users.get(0).getName());
    }
}

Пояснення:

  • Ми використовуємо анотацію @DataJpaTest, щоб автоматично підключити вбудовану базу даних (наприклад, H2).
  • У блоці Arrange додаємо тестові дані в репозиторій.
  • У блоці Act виконується тестований метод.
  • У блоці Assert перевіряються результати.

Інтеграційне тестування

Іноді треба протестувати застосунок повністю, включно з усіма рівнями — від контролерів до бази даних. Для цього використовуємо @SpringBootTest.

Приклад:


@SpringBootTest
public class IntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testGetUsers() throws Exception {
        mockMvc.perform(get("/users"))
                .andExpect(status().isOk())
                .andExpect(content().string("[\"Alice\",\"Bob\",\"Charlie\"]"));
    }
}

Важливі моменти

1. Використання H2 для тестування.

Spring Boot автоматично підключає H2 Database у тестах, якщо ви використовуєте JPA. Це дозволяє тестувати базу даних без потреби піднімати реальний сервер.

2. Використання mock-об'єктів з Mockito.

Mockito дозволяє "мокати" залежності, щоб ізолювати код, що тестується. Наприклад:


@MockBean
private UserService userService;

@Test
public void testMockedService() {
    when(userService.getUsers()).thenReturn(List.of("MockedUser"));

    // Your test code here
}

Переваги тестування з Spring Boot

  • Зручна інтеграція. Всі інструменти інтегровані, не потрібно нічого налаштовувати вручну.
  • Ефективність. Тести запускаються швидко, навіть при використанні вбудованої бази даних.
  • Надійність. Хороше покриття тестами дозволяє уникнути несподіваних проблем у продакшені.

Тепер ви озброєні всіма базовими знаннями, потрібними для тестування Spring Boot-застосунків. Пам'ятайте, будь-які зміни в коді заслуговують на перевірку тестами. Тестуйте все, що рухається (і навіть те, що ще не рухається). І, як кажуть, "кращий маленький тест, ніж велике вибачення перед замовником".

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ