Переход с JUnit 4 на JUnit 5

Переход с JUnit 4 на JUnit 5

1. обзор

В этой статье мы увидим, как перейти с JUnit 4 на последнюю версию JUnit 5, с обзором различий между двумя версиями библиотеки.

Общие рекомендации по использованию JUnit 5 см. В нашей статьеhere.

2. JUnit 5 Преимущества

Начнем с предыдущей версии - JUnit 4 имеет некоторые четкие ограничения:

  • Вся структура содержалась в одной библиотеке jar. Вся библиотека должна быть импортирована, даже когда требуется только определенная функция. In JUnit 5, we get more granularity and can import only what is necessaryс

  • Один исполнитель тестов может одновременно выполнять тесты только в JUnit 4 (например, SpringJUnit4ClassRunner илиParameterized). JUnit 5 allows multiple runners to work simultaneously

  • JUnit 4 никогда не выходил за пределы Java 7, упуская множество функций из Java 8. JUnit 5 makes good use of Java 8 featuresс

Идея JUnit 5 заключалась в том, чтобы полностью переписать JUnit 4, чтобы устранить большинство из этих недостатков.

3. Различия

JUnit 4 был разделен на модули, которые составляют JUnit 5:

  • JUnit Platform – этот модуль охватывает все фреймворки расширений, которые могут быть нам интересны в выполнении тестов, обнаружении и составлении отчетов.

  • JUnit Vintage – этот модуль обеспечивает обратную совместимость с JUnit 4 или даже JUnit 3

3.1. Аннотации

JUnit 5 содержит важные изменения в своих аннотациях. The most important one is that we can no longer use @Test annotation for specifying expectations.с

Параметрexpected в JUnit 4:

@Test(expected = Exception.class)
public void shouldRaiseAnException() throws Exception {
    // ...
}

Теперь мы можем использовать методassertThrows:

public void shouldRaiseAnException() throws Exception {
    Assertions.assertThrows(Exception.class, () -> {
        //...
    });
}

Атрибутtimeout в JUnit 4:

@Test(timeout = 1)
public void shouldFailBecauseTimeout() throws InterruptedException {
    Thread.sleep(10);
}

Теперь методassertTimeout в JUnit 5:

@Test
public void shouldFailBecauseTimeout() throws InterruptedException {
    Assertions.assertTimeout(Duration.ofMillis(1), () -> Thread.sleep(10));
}

Другие аннотации, которые были изменены в JUnit 5:

  • Аннотация@Before переименована в@BeforeEach

  • Аннотация@After переименована в@AfterEach

  • Аннотация@BeforeClass переименована в@BeforeAll

  • Аннотация@AfterClass переименована в@AfterAll

  • Аннотация@Ignore переименована в@Disabled

3.2. Утверждения

Теперь мы можем написать сообщения с утверждениями в лямбда-выражениях в JUnit 5, что позволяет при отложенной оценке пропускать сложное построение сообщения до тех пор, пока это не потребуется:

@Test
public void shouldFailBecauseTheNumbersAreNotEqual_lazyEvaluation() {
    Assertions.assertTrue(
      2 == 3,
      () -> "Numbers " + 2 + " and " + 3 + " are not equal!");
}

Мы также можем сгруппировать утверждения в JUnit 5:

@Test
public void shouldAssertAllTheGroup() {
    List list = Arrays.asList(1, 2, 4);
    Assertions.assertAll("List is not incremental",
        () -> Assertions.assertEquals(list.get(0).intValue(), 1),
        () -> Assertions.assertEquals(list.get(1).intValue(), 2),
        () -> Assertions.assertEquals(list.get(2).intValue(), 3));
}

3.3. Предположения

Новый классAssumptions теперь находится вorg.junit.jupiter.api.Assumptions. JUnit 5 полностью поддерживает существующие методы предположений в JUnit 4, а также добавляет набор новых методов, позволяющих запускать некоторые утверждения только при определенных сценариях:

@Test
public void whenEnvironmentIsWeb_thenUrlsShouldStartWithHttp() {
    assumingThat("WEB".equals(System.getenv("ENV")),
      () -> {
          assertTrue("http".startsWith(address));
      });
}

3.4. Пометка и фильтрация

В JUnit 4 мы могли группировать тесты с помощью аннотации@Category. В JUnit 5 аннотация@Category заменяется аннотацией@Tag:

@Tag("annotations")
@Tag("junit5")
@RunWith(JUnitPlatform.class)
public class AnnotationTestExampleTest {
    /*...*/
}

Мы можем включать / исключать определенные теги, используяmaven-surefire-plugin:


    
        
            maven-surefire-plugin
            
                
                    junit5
                
            
        
    

3.5. Новые аннотации для запуска тестов

@RunWith использовался для интеграции контекста теста с другими фреймворками или для изменения общего потока выполнения в тестовых примерах в JUnit 4.

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

В качестве примера, чтобы использовать функции Spring в JUnit 4:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  {"/app-config.xml", "/test-data-access-config.xml"})
public class SpringExtensionTest {
    /*...*/
}

Теперь в JUnit 5 это простое расширение:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(
  { "/app-config.xml", "/test-data-access-config.xml" })
public class SpringExtensionTest {
    /*...*/
}

3.6. Новые аннотации правил испытаний

В JUnit 4 аннотации@Rule и @ClassRule использовались для добавления специальных функций в тесты.

В Юнит 5. мы можем воспроизвести ту же логику, используя аннотацию@ExtendWith.

Например, скажем, у нас есть пользовательское правило в JUnit 4 для записи трассировок журнала до и после теста:

public class TraceUnitTestRule implements TestRule {

    @Override
    public Statement apply(Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                // Before and after an evaluation tracing here
                ...
            }
        };
    }
}

И мы реализуем это в тестовом наборе:

@Rule
public TraceUnitTestRule traceRuleTests = new TraceUnitTestRule();

В JUnit 5 мы можем написать то же самое гораздо более интуитивно понятным способом:

public class TraceUnitExtension implements AfterEachCallback, BeforeEachCallback {

    @Override
    public void beforeEach(TestExtensionContext context) throws Exception {
        // ...
    }

    @Override
    public void afterEach(TestExtensionContext context) throws Exception {
        // ...
    }
}

Используя интерфейсыAfterEachCallback иBeforeEachCallback JUnit 5, доступные в пакетеorg.junit.jupiter.api.extension,, мы легко реализуем это правило в наборе тестов:

@RunWith(JUnitPlatform.class)
@ExtendWith(TraceUnitExtension.class)
public class RuleExampleTest {

    @Test
    public void whenTracingTests() {
        /*...*/
    }
}

3.7. Юнит 5 Винтаж

JUnit Vintage помогает в миграции тестов JUnit, выполняя тесты JUnit 3 или JUnit 4 в контексте JUnit 5.

Мы можем использовать его, импортировав JUnit Vintage Engine:


    org.junit.vintage
    junit-vintage-engine
    ${junit5.vintage.version}
    test

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

Как мы видели в этой статье, JUnit 5 - это модульный и современный подход к структуре JUnit 4. Мы ввели основные различия между этими двумя версиями и намекнули, как перейти с одной на другую.

Полную реализацию этого руководства можно найти вover on GitHub.