Короткий ответ
Unit-тест проверяет отдельный компонент — один класс или метод — в изоляции от остальной системы: это «белый ящик», такие тесты быстрые и обычно пишутся самим разработчиком. Интеграционный тест проверяет взаимодействие модулей или слоёв приложения (сервиса с базой, контроллера с сервисом) и корректность работы с внешними зависимостями; он выполняется после unit-тестов и работает медленнее.
Как это работает подробнее
Коротко: unit-тест отвечает на вопрос «корректно ли работает этот класс сам по себе», а интеграционный — «корректно ли модули работают вместе». Тестирование нужно, чтобы находить дефекты на ранних стадиях (это дешевле исправления в проде), проверять соответствие требованиям, снижать риск отказов и повышать уверенность при изменении кода.
- JUnit — основной фреймворк unit-тестирования; в JUnit 5 используются
@Test,@BeforeEach/@AfterEach,@BeforeAll/@AfterAllи классы-ассерты. - Mockito — библиотека моков:
when(...).thenReturn(...)задаёт ожидаемое поведение,verify(...)проверяет, что методы вызывались нужное число раз. - Mock vs stub: mock имитирует поведение реального объекта и проверяет ожидаемые вызовы; stub — «заглушка», которая просто возвращает заранее заданные ответы, обычно без проверки взаимодействия.
- Spring: JUnit, Mockito, AssertJ и Spring Test входят в стартер
spring-boot-starter-test.
Пример кода
UserServiceTest.java
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository repository;
@InjectMocks
private UserService service;
@Test
void getUserReturnsUser() {
when(repository.findById(1L))
.thenReturn(Optional.of(new User(1L, "Alice")));
User user = service.getUser(1L);
assertEquals("Alice", user.getName());
verify(repository).findById(1L);
}
}