Migration de JUnit 4 à JUnit 5

Migration de JUnit 4 à JUnit 5

1. Vue d'ensemble

Dans cet article, nous allons voir comment nous pouvons migrer de JUnit 4 vers la dernière version de JUnit 5 - avec un aperçu des différences entre les deux versions de la bibliothèque.

Pour les instructions générales sur l'utilisation de JUnit 5, consultez notre articlehere.

2. JUnit 5 Avantages

Commençons par la version précédente - JUnit 4 a des limitations claires:

  • Le cadre entier était contenu dans une seule bibliothèque de bocaux. Toute la bibliothèque doit être importée même lorsqu'une seule fonctionnalité est requise. In JUnit 5, we get more granularity and can import only what is necessary

  • Un exécuteur de tests ne peut exécuter que des tests dans JUnit 4 à la fois (par exemple, SpringJUnit4ClassRunner ouParameterized). JUnit 5 allows multiple runners to work simultaneously

  • JUnit 4 n’a jamais dépassé Java 7, manquant de nombreuses fonctionnalités de Java 8. JUnit 5 makes good use of Java 8 features

L'idée derrière JUnit 5 était de réécrire complètement JUnit 4 pour résoudre la plupart de ces inconvénients.

3. Différences

JUnit 4 était divisé en modules comprenant JUnit 5:

  • JUnit Platform – ce module couvre tous les frameworks d'extension qui pourraient nous intéresser dans l'exécution des tests, la découverte et la création de rapports

  • JUnit Vintage – ce module permet une rétrocompatibilité avec JUnit 4 ou même JUnit 3

3.1. Annotations

JUnit 5 apporte des modifications importantes à ses annotations. The most important one is that we can no longer use @Test annotation for specifying expectations.

Le paramètreexpected dans JUnit 4:

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

Maintenant, nous pouvons utiliser une méthodeassertThrows:

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

L'attributtimeout dans JUnit 4:

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

Maintenant, la méthodeassertTimeout dans JUnit 5:

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

Autres annotations modifiées dans JUnit 5:

  • L'annotation@Before est renommée en@BeforeEach

  • L'annotation@After est renommée en@AfterEach

  • L'annotation@BeforeClass est renommée en@BeforeAll

  • L'annotation@AfterClass est renommée en@AfterAll

  • L'annotation@Ignore est renommée en@Disabled

3.2. Assertions

Nous pouvons maintenant écrire des messages d'assertion dans un lambda dans JUnit 5, permettant ainsi à l'évaluation paresseuse de sauter la construction de message complexe jusqu'à ce que cela soit nécessaire:

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

Nous pouvons également regrouper des assertions dans 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. Hypothèses

La nouvelle classeAssumptions est maintenant enorg.junit.jupiter.api.Assumptions. JUnit 5 prend entièrement en charge les méthodes d'hypothèses existantes dans JUnit 4 et ajoute également un ensemble de nouvelles méthodes permettant d'exécuter certaines assertions uniquement dans des scénarios spécifiques:

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

3.4. Marquage et filtrage

Dans JUnit 4, nous pourrions regrouper les tests en utilisant l'annotation@Category. Avec JUnit 5, l'annotation@Category est remplacée par l'annotation@Tag:

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

Nous pouvons inclure / exclure des balises particulières en utilisant lesmaven-surefire-plugin:


    
        
            maven-surefire-plugin
            
                
                    junit5
                
            
        
    

3.5. Nouvelles annotations pour l'exécution de tests

Le@RunWith a été utilisé pour intégrer le contexte de test avec d'autres frameworks ou pour modifier le flux global d'exécution dans les cas de test de JUnit 4.

Avec JUnit 5, nous pouvons désormais utiliser l'annotation@ExtendWith pour fournir des fonctionnalités similaires.

Par exemple, pour utiliser les fonctionnalités de Spring dans JUnit 4:

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

Maintenant, dans JUnit 5, il s’agit d’une simple extension:

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

3.6. Nouvelles règles de test Annotations

Dans JUnit 4, les annotations@Rule et @ClassRule ont été utilisées pour ajouter des fonctionnalités spéciales aux tests.

Dans JUnit 5. nous pouvons reproduire la même logique en utilisant l'annotation@ExtendWith.

Par exemple, disons que nous avons une règle personnalisée dans JUnit 4 pour écrire les traces de journal avant et après un test:

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
                ...
            }
        };
    }
}

Et nous l’implémentons dans une suite de tests:

@Rule
public TraceUnitTestRule traceRuleTests = new TraceUnitTestRule();

Dans JUnit 5, nous pouvons écrire la même chose d'une manière beaucoup plus intuitive:

public class TraceUnitExtension implements AfterEachCallback, BeforeEachCallback {

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

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

En utilisant les interfacesAfterEachCallback etBeforeEachCallback de JUnit 5 disponibles dans le packageorg.junit.jupiter.api.extension,, nous implémentons facilement cette règle dans la suite de tests:

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

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

3.7. JUnit 5 Vintage

JUnit Vintage facilite la migration des tests JUnit en exécutant des tests JUnit 3 ou JUnit 4 dans le contexte JUnit 5.

Nous pouvons l'utiliser en important le JUnit Vintage Engine:


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

4. Conclusion

Comme nous l'avons vu dans cet article, JUnit 5 est une version modulaire et moderne du framework JUnit 4. Nous avons présenté les principales différences entre ces deux versions et indiqué comment migrer de l'une à l'autre.

L'implémentation complète de ce didacticiel se trouve dansover on GitHub.