Давайте почнемо з самого початку. Навіщо взагалі потрібне тестування? Ви ж не хочете, щоб ваші користувачі натрапили на баги в продакшені, правда? Тестування дозволяє знаходити й усувати проблеми ще до того, як вони завдадуть шкоди вашому застосунку або вашій репутації. А 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-застосунків. Пам'ятайте, будь-які зміни в коді заслуговують на перевірку тестами. Тестуйте все, що рухається (і навіть те, що ще не рухається). І, як кажуть, "кращий маленький тест, ніж велике вибачення перед замовником".
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ