Оглавление
JUnit & Mockito
Тестирование Java-кода: тесты JUnit, проверки, параметризованные тесты и заглушки Mockito.
1.Начало работы
- Зачем нужны тесты и что такое JUnitЧто дают автоматические тесты, как JUnit, Mockito и AssertJ делят работу, какие версии использует курс и что мы будем тестировать.
- Настройка проектаMaven-проект для тестов: BOM JUnit, зависимость junit-jupiter, плагин Surefire, папка src/test/java и первый тестируемый класс.
- Первый тестТестовый класс, аннотация @Test, assertEquals и схема «подготовка, действие, проверка» на примере калькулятора цен.
- Запуск тестов и чтение результатовmvn test, запуск одного класса или метода, как читать отчёт Surefire, чем падение отличается от ошибки и какие классы считаются тестами.
2.Основы JUnit
- ПроверкиОсновные проверки JUnit: assertEquals, assertTrue, assertNull, assertIterableEquals, сообщения при падении и группировка проверок через assertAll.
- Исключения и время выполненияКак проверить через assertThrows, что код выбрасывает нужное исключение, проверить его сообщение, убедиться в отсутствии исключения и ограничить время работы через assertTimeout.
- Жизненный цикл тестаСервис блога под тестом, подготовка свежих объектов через @BeforeEach, уборка через @AfterEach, однократная настройка через @BeforeAll и @AfterAll и почему каждый тест получает новый экземпляр класса.
- Понятные имена и вложенные классы@DisplayName для человекочитаемых имён тестов и @Nested для группировки тестов одного класса по ситуациям, с общей и вложенной подготовкой.
- Отключение, допущения и тегиВременное отключение теста через @Disabled, пропуск по условию через допущения и @EnabledOnOs, пометка тестов через @Tag и запуск только части групп через Maven.
3.Больше возможностей JUnit
- Параметризованные тестыОдин тест для многих входных данных: @ParameterizedTest с @ValueSource, @NullAndEmptySource и @CsvSource, понятные имена запусков и кавычки в CSV.
- Данные из метода: @MethodSourceКогда аннотаций не хватает: передача объектов вроде BigDecimal и записей в параметризованный тест из фабричного метода через @MethodSource и Arguments.
- Временные файлы: @TempDirТестирование кода, который пишет файлы: временная папка от JUnit через @TempDir на поле или параметре и почему тесты не должны писать по фиксированным путям.
- Цепочки проверок с AssertJПодключение AssertJ, цепочки assertThat для строк, чисел, BigDecimal и коллекций, извлечение полей записей, проверка исключений и чтение сообщений AssertJ.
- Повторяемые и динамические тесты, порядок тестовЗапуск теста несколько раз через @RepeatedTest и RepetitionInfo, создание тестов во время работы через @TestFactory и DynamicTest и порядок тестов через @TestMethodOrder и @Order.
- Мягкие проверки и ещё проверки AssertJСбор всех падений теста через SoftAssertions и assertSoftly из AssertJ, сравнение с assertAll из JUnit и проверки satisfies, allSatisfy и usingRecursiveComparison.
4.Mockito
- Моки: mock, when, thenReturnЗачем модульный тест подменяет зависимости, подключение Mockito с настройкой Java-агента для современных JDK, создание мока и задание ответов через when и thenReturn.
- Проверка вызовов: verifyКак через verify проверить, что сервис вызвал зависимость с нужными аргументами, нужное число раз или не вызвал вовсе, и как читать сообщения Mockito.
- Сопоставители аргументов и ArgumentCaptorНастройка и проверка вызовов с любым аргументом через any, anyLong, eq и contains, вычисление ответа через thenAnswer и перехват аргумента через ArgumentCaptor.
- Ошибки зависимостей: thenThrow и doThrowИмитация упавшей базы или почтового сервера через thenThrow, doThrow для void-методов, разные ответы на последовательные вызовы и правило о проверяемых исключениях.
- @Mock и @InjectMocks с MockitoExtensionСоздание моков аннотациями: @ExtendWith(MockitoExtension.class), @Mock, @InjectMocks и @Captor, а также строгая проверка заглушек и UnnecessaryStubbingException.
- ШпионыЧто такое шпион в Mockito, чем он отличается от мока, проверка вызовов на настоящем объекте и подмена одного метода через doReturn.
- Порядок вызовов, статические методы и конструкторыПроверка порядка вызовов через InOrder, подмена статических методов вроде LocalDate.now через mockStatic, перехват new через mockConstruction и почему лучше передавать Clock.
- Стиль BDD: given, willReturn, then, shouldТесты Mockito в стиле given-when-then через BDDMockito, названия тестов по ситуации и результату и создание шпионов аннотацией @Spy.
5.Хорошие тесты
- Каким должен быть хороший тестСвойства хороших модульных тестов, что тестировать и что нет, сколько моков — уже слишком, имена тестов и почему тесты не должны делить состояние.
- Покрытие тестами с JaCoCoЧто измеряет покрытие кода, подключение плагина JaCoCo к Maven вместе с агентом Mockito, чтение HTML-отчёта и почему 100% — не цель.