Руководство по JUnit 5

1. Обзор

JUnit - одна из самых популярных платформ модульного тестирования в экосистеме Java. Хотя текущей стабильной версией является JUnit 4.12, версия 5.1.0 содержит ряд интересных нововведений с целью поддержки новых функций в Java 8 и более поздних версиях , а также включения множества различных стилей тестирования.

Эта статья является продолжением нашей ссылки:/junit-5-preview[предварительный просмотр JUnit 5].

2. Зависимости Maven

Настройка JUnit 5.x.0 довольно проста, нам нужно добавить следующую зависимость в наш pom. xml :

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.1.0</version>
    <scope>test</scope>
</dependency>

Важно отметить, что эта версия требует Java 8 для работы .

Более того, теперь есть прямая поддержка для запуска модульных тестов на платформе JUnit в Eclipse, а также IntelliJ. Конечно, вы также можете запускать тесты, используя цель Maven Test.

С другой стороны, IntelliJ поддерживает JUnit 5 по умолчанию. Поэтому запустить JUnit 5 на IntelliJ довольно просто, просто щелкните правой кнопкой мыши → Run или Ctrl-Shift-F10.

3. Архитектура

JUnit 5 состоит из нескольких разных модулей из трех разных подпроектов:

3.1. Платформа JUnit

Платформа отвечает за запуск сред тестирования на JVM.

Он определяет стабильный и мощный интерфейс между JUnit и его клиентом, таким как инструменты сборки.

Конечная цель - как легко интегрировать своих клиентов с JUnit в обнаружение и выполнение тестов.

Он также определяет TestEngine API для разработки инфраструктуры тестирования, работающей на платформе JUnit.

Таким образом, вы можете подключить сторонние библиотеки тестирования непосредственно в JUnit, реализовав собственный TestEngine.

3.2. Юнит Юпитер

Этот модуль включает новые модели программирования и расширения для написания тестов в JUnit 5. Новые аннотации по сравнению с JUnit 4:

  • @ TestFactory - обозначает метод, который является фабрикой тестов для динамического

тесты ** @ DisplayName - определяет настраиваемое отображаемое имя для тестового класса или

Метод испытания ** @ Nested - обозначает, что аннотированный класс является вложенным, нестатическим

тестовый класс ** @ Tag - объявляет теги для фильтрации тестов

  • @ ExtendWith - используется для регистрации пользовательских расширений

  • @ BeforeEach – обозначает, что аннотированный метод будет выполнен

перед каждым методом испытаний (ранее @ Before ) ** @ AfterEach - обозначает, что аннотированный метод будет выполнен

после каждого метода испытаний (ранее @ After ) ** @ BeforeAll - обозначает, что аннотированный метод будет выполнен

перед всеми тестовыми методами в текущем классе (ранее @ BeforeClass ) ** @ AfterAll - обозначает, что аннотированный метод будет выполнен после

все методы тестирования в текущем классе (ранее @ AfterClass ) ** @ Disable - используется для отключения тестового класса или метода (ранее

@ Ignore )

3.3. Юнит Винтаж

Поддерживает запуск тестов на основе JUnit 3 и JUnit 4 на платформе JUnit 5.

4. Основные аннотации

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

4.1. @ BeforeAll и @ BeforeEach

Ниже приведен пример простого кода, выполняемого перед основными тестовыми примерами:

@BeforeAll
static void setup() {
    log.info("@BeforeAll - executes once before all test methods in this class");
}

@BeforeEach
void init() {
    log.info("@BeforeEach - executes before each test method in this class");
}

Важно отметить, что метод с аннотацией @ BeforeAll должен быть статическим, иначе код не будет компилироваться.

4.2. @ DisplayName и @ Disabled

Давайте перейдем к новым опциональным методам тестирования:

@DisplayName("Single test successful")
@Test
void testSingleSuccessTest() {
    log.info("Success");
}

@Test
@Disabled("Not implemented yet")
void testShowSomething() {
}

Как мы видим, мы можем изменить отображаемое имя или отключить метод с комментарием, используя новые аннотации.

4.3. @ AfterEach и @ AfterAll

Наконец, давайте обсудим методы, связанные с операциями после выполнения тестов:

@AfterEach
void tearDown() {
    log.info("@AfterEach - executed after each test method.");
}

@AfterAll
static void done() {
    log.info("@AfterAll - executed after all test methods.");
}

Обратите внимание, что метод с @ AfterAll также должен быть статическим методом.

5. Утверждения и предположения

Пожалуйста, обратитесь к этой ссылке:/junit-5-preview[tutorial]на JUnit5.

6. Тестирование исключений

В JUnit 5 есть два способа тестирования исключений. Оба они могут быть реализованы с помощью метода assertThrows () :

@Test
void shouldThrowException() {
    Throwable exception = assertThrows(UnsupportedOperationException.class, () -> {
      throw new UnsupportedOperationException("Not supported");
    });
    assertEquals(exception.getMessage(), "Not supported");
}

@Test
void assertThrowsException() {
    String str = null;
    assertThrows(IllegalArgumentException.class, () -> {
      Integer.valueOf(str);
    });
}

Первый пример используется для проверки более подробной информации о сгенерированном исключении, а второй только проверяет тип исключения.

7. Test Suites

Чтобы продолжить новые функции JUnit 5, мы попытаемся познакомиться с концепцией объединения нескольких классов тестов в набор тестов, чтобы мы могли запускать их вместе. JUnit 5 предоставляет две аннотации:

@ SelectPackages и @ SelectClasses для создания тестовых наборов.

Помните, что на этой ранней стадии большинство IDE не поддерживают эти функции.

Давайте посмотрим на первый:

@RunWith(JUnitPlatform.class)
@SelectPackages("com.baeldung")
public class AllTests {}

@ SelectPackage используется для указания имен пакетов, которые будут выбраны при запуске набора тестов. В нашем примере все тесты будут запущены. Вторая аннотация @ SelectClasses используется для указания классов, которые должны быть выбраны при запуске набора тестов:

@RunWith(JUnitPlatform.class)
@SelectClasses({AssertionTest.class, AssumptionTest.class, ExceptionTest.class})
public class AllTests {}

Например, вышеупомянутый класс создаст набор, содержащий три тестовых класса. Обратите внимание, что занятия не обязательно должны быть в одном пакете.

8. Динамические тесты

Последней темой, которую мы хотим представить, является функция динамических тестов JUnit 5, которая позволяет объявлять и запускать тестовые примеры, сгенерированные во время выполнения. В отличие от статических тестов, которые определяют фиксированное количество тестовых примеров во время компиляции, динамические тесты позволяют нам динамически определять тестовые случаи во время выполнения.

Динамические тесты могут быть сгенерированы фабричным методом, аннотированным @TestFactory. Давайте посмотрим на пример кода:

@TestFactory
public Stream<DynamicTest> translateDynamicTestsFromStream() {
    return in.stream()
      .map(word ->
          DynamicTest.dynamicTest("Test translate " + word, () -> {
            int id = in.indexOf(word);
            assertEquals(out.get(id), translate(word));
          })
    );
}

Этот пример очень прост и понятен. Мы хотим перевести слова, используя два ArrayList , названные in и out , соответственно. Фабричный метод должен возвращать Stream , Collection , Iterable или Iterator . В нашем случае мы выбираем Java 8 Stream.

Обратите внимание, что методы @ TestFactory не должны быть частными или статическими.

Количество тестов является динамическим и зависит от размера ArrayList .

9. Заключение

В обзоре был краткий обзор изменений, которые появятся в JUnit 5.

Мы видим, что в JUnit 5 произошли большие изменения в архитектуре, связанные с модулем запуска платформы, интеграцией со средством сборки, IDE, другими платформами модульного тестирования и т. Д. Кроме того, JUnit 5 более интегрирован с Java 8, особенно с концепциями Lambdas и Stream. ,

Примеры, используемые в этой статье, можно найти в проекте GitHub .