Ответ
Модульное (Unit) тестирование — это уровень тестирования программного обеспечения, при котором проверяется корректность работы минимальных изолированных частей приложения — модулей (юнитов). В контексте ООП юнитом обычно является отдельный класс или метод.
Ключевые цели unit-тестирования:
- Обеспечение корректности: Проверка, что каждая часть программы работает в соответствии с техническим заданием (спецификацией) при различных входных данных (включая граничные случаи).
- Раннее обнаружение дефектов: Ошибки выявляются на этапе разработки, что значительно дешевле их исправления на поздних стадиях или в production.
- Облегчение рефакторинга: Набор unit-тестов (тестовый набор) служит "страховочной сеткой", позволяя безопасно изменять и улучшать код, будучи уверенным, что существующая функциональность не сломана.
- Живая документация: Тесты демонстрируют, как должен использоваться модуль и какое поведение от него ожидается.
- Улучшение дизайна: Написание тестируемого кода часто приводит к более модульной, слабосвязанной архитектуре.
Пример unit-теста с использованием JUnit 5 и Mockito:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class PaymentServiceTest {
@Test
void processPayment_ShouldReturnTrue_WhenPaymentIsSuccessful() {
// 1. ARRANGE (Подготовка)
// Создаем mock-объект зависимого сервиса
PaymentGateway mockGateway = mock(PaymentGateway.class);
// Задаем поведение mock: при вызове pay() с любыми аргументами вернуть true
when(mockGateway.pay(anyDouble())).thenReturn(true);
// Создаем тестируемый сервис, инжектим mock-зависимость
PaymentService service = new PaymentService(mockGateway);
// 2. ACT (Действие)
boolean result = service.processPayment(100.50, "order_123");
// 3. ASSERT (Проверка)
assertTrue(result); // Проверяем ожидаемый результат
// Проверяем, что метод pay был вызван ровно один раз с конкретным аргументом
verify(mockGateway, times(1)).pay(100.50);
}
@Test
void calculateDiscount_ShouldApplyTenPercent_ForAmountOver1000() {
// Тест чистой функции без зависимостей
PaymentService service = new PaymentService(null);
double result = service.calculateDiscount(1500.0);
assertEquals(150.0, result, 0.001); // Проверка с дельтой для double
}
}
Основной принцип: Один тест проверяет один конкретный сценарий (use case) для одного модуля.