JUnit: самое важное



Информация ниже не новая, но очень важная. Так что грех не повторить:)



Ниже особенности и фичи JUnit, которые полезно знать большинству разработчиков. Если что-то заинтересовало и непонятно — поможет JUnit 5 User Guide



1️⃣ Жизненный цикл теста



Каждый тест — это метод с аннотацией @Test.



Через аннотацию @DisplayName задаётся симпатичное имя теста в отчёте.



Чтобы выполнить что-то до или после выполнения теста, используются методы с аннотациями:

▫️ @Before, @BeforeAll

▫️ @After, @AfterAll



JUnit создаёт новый экземпляр класса на каждый тестовый метод. Класс ServiceTest с пятью методами @Test во время запуска превратится в 5 экземпляров класса ServiceTest.



Благодаря этому тесты выполняются независимо.



Этим JUnit отличается от TestNG, где создаётся один экземпляр класса на все тестовые методы. Если хочется как в TestNG, добавьте над классом аннотацию @TestInstance(Lifecycle.PER_CLASS)



2️⃣ Проверки



Сердце каждого теста - методы с приставкой assert*:

🔸 assertTrue

🔸 assertEquals

🔸 assertInstanceOf



В самом JUnit мало методов, более удобные ассерты есть в библиотеках Hamсrest и AssertJ. AssertJ, на мой взгляд, более читабельный, но Hamсrest используется чаще.



3️⃣ Группировка тестов



Аннотация @Tag("groupName") объединяет тесты в группы. Работает и для одного теста, и для класса.



Можно указывать тэги в системе сборки и при запуске тестов из IDE.



4️⃣ Отключение тестов



Аннотация @Disabled. Есть продвинутые варианты, можно отключить тесты для

▫️ операционной системы

@DisabledOnOs(WINDOWS)

▫️ версии java

@DisabledOnJre(JAVA_9)

@DisabledForJreRange(min = JAVA_9)

▫️ системных переменных:

@DisabledIfSystemProperty(named = "ci-server", matches = "true")

@DisabledIfEnvironmentVariable(named = "ENV", matches = ".*development.*")



5️⃣ Параметризированные тесты



Помогают запустить один тест с разными аргументами. Выглядит так:



@ParameterizedTest

@ValueSource(ints={100,-14})

public void test(int input) {}



Такой тест запустится дважды - с аргументом 100 и -14.



Вместо готового списка можно брать значения

🔸 из CSV файла @CsvSource

🔸 из метода @MethodSource



6️⃣ Проверка таймаута



▫️ Через ассерт

assertTimeout(ofMinutes(2), ()->{});

▫️ Через аннотацию

@Timeout(value=42,unit=SECONDS)



7️⃣ Полезные библиотеки



▫️ Hamсrest, AssertJ — расширенные библиотеки методов-ассертов

▫️ Mockito для заглушек. Добавляете библиотеку в pom.xml или build.gradle, а в тест - аннотацию @ExtendWith(MockitoExtension.class)

▫️ Testcontainers для запуска внешних компонентов в докере. Добавляем библиотеку, аннотацию @Testcontainers над классом и @Container над компонентом

▫️ Java Faker — генератор данных для тестов



Ещё я когда-то писала 2 хороших поста на тему, чем отличается JUnit 4 от Unit 5. Если вас удивляет, почему там разные аннотации и почему версии не совместимы друг с другом, то почитайте:)