[JAVA] J'ai examiné le cycle de vie de l'extension de JUnit Jupiter

Quel est le cycle de vie d'une instance d'extension essayant d'écrire une extension pour JUnit 5 (JUnit Jupiter)? Comme c'est devenu, rédigez un mémorandum.

environnement

TL;TR

Examen du modèle d'extension

Le modèle d'extension de JUnit 5 est un mécanisme de standardisation du pré-traitement, du post-traitement, du traitement des exceptions, etc. pour chaque test. Le degré de liberté est inférieur à celui de la Rule de Junit 4, mais vous pouvez facilement créer une extension simplement en implémentant une interface qui prend en charge les points d'extension.

Il existe trois façons d'utiliser l'extension.

  1. Enregistrez l'extension avec @ Extension.
  2. Enregistrez l'extension par programme avec @ RegisterExtension.
  3. Enregistrez-vous automatiquement avec Service Loader.

Cette fois, utilisez les méthodes 1 et 2 pour vérifier quand l'instance d'extension est créée.

Les extensions utilisées pour la confirmation sont les suivantes.

FooExtension.java


import org.junit.jupiter.api.extension.*;

public class FooExtension implements BeforeEachCallback, AfterEachCallback, BeforeAllCallback, AfterAllCallback {

    {
        System.out.println(String.format("[%s] created", this.toString()));
    }

    @Override
    public void beforeAll(ExtensionContext extensionContext) throws Exception {
        System.out.println(String.format("[%s] before all", this.toString()));
    }

    @Override
    public void beforeEach(ExtensionContext context) throws Exception {
        System.out.println(String.format("[%s] before each", this.toString()));
    }

    @Override
    public void afterEach(ExtensionContext extensionContext) throws Exception {
        System.out.println(String.format("[%s] after each", this.toString()));
    }

    @Override
    public void afterAll(ExtensionContext extensionContext) throws Exception {
        System.out.println(String.format("[%s] after all", this.toString()));
    }
}

Enregistrer l'extension avec @ Extension

La source

@ExtendWith(FooExtension.class)
public class ExtensionTest {

    @Test
    void test1() { System.out.println("test 1"); }

    @Test
    void test2() { System.out.println("test 2"); }

    @Test
    void test3() { System.out.println("test 3"); }
}

résultat

[example.FooExtension@70325e14] created
[example.FooExtension@70325e14] before all
[example.FooExtension@70325e14] before each
test 1
[example.FooExtension@70325e14] after each
[example.FooExtension@70325e14] before each
test 2
[example.FooExtension@70325e14] after each
[example.FooExtension@70325e14] before each
test 3
[example.FooExtension@70325e14] after each
[example.FooExtension@70325e14] after all

Vous pouvez voir que chaque test partage une instance d'extension. Une instance d'ExtensionTest est créée pour chaque test, mais le même résultat a été obtenu lors du changement de partage de l'instance extensionTest avec @TestInstance (Lifecycle.PER_CLASS).

@ RegisterExtension + Register Extension avec champ statique

La source

SecondExtensionTest.java


public class SecondExtensionTest {

    @RegisterExtension
    static FooExtension fooExtension = new FooExtension();

    @Test
    void test1() { System.out.println("test 1"); }

    @Test
    void test2() { System.out.println("test 2"); }

    @Test
    void test3() { System.out.println("test 3"); }
}

résultat

[example.FooExtension@55183b20] created
[example.FooExtension@55183b20] before all
[example.FooExtension@55183b20] before each
test 1
[example.FooExtension@55183b20] after each
[example.FooExtension@55183b20] before each
test 2
[example.FooExtension@55183b20] after each
[example.FooExtension@55183b20] before each
test 3
[example.FooExtension@55183b20] after each
[example.FooExtension@55183b20] after all

Bien sûr, puisqu'il s'agit d'un champ statique, la même instance est partagée.

Register Extension avec @ RegisterExtension + champ non statique

Supprimons le static de la fooExtension du SecondExtensionTest plus tôt.

Pour Lifecycle.PER_METHOD

La source

SecondExtensionTest.java


public class SecondExtensionTest {

    @RegisterExtension
-   static FooExtension fooExtension = new FooExtension();
+   FooExtension fooExtension = new FooExtension();

    //Omission
}

résultat

[example.FooExtension@40a4337a] created
[example.FooExtension@40a4337a] before each
test 1
[example.FooExtension@40a4337a] after each
[example.FooExtension@fa4c865] created
[example.FooExtension@fa4c865] before each
test 2
[example.FooExtension@fa4c865] after each
[example.FooExtension@3bd82cf5] created
[example.FooExtension@3bd82cf5] before each
test 3
[example.FooExtension@3bd82cf5] after each

Vous pouvez voir que chaque test a une instance d'Extension différente. En effet, une instance de SecondExtensionTest lui-même est générée pour chaque test. BeforeAll et AfterAll ne fonctionnent pas, mais vous devez les rendre statiques dans le cas de Lifecycle.PER_METHOD ainsi que lorsque vous ajoutez @ BeforeAll à la méthode.

Pour Lifecycle.PER_CLASS

Alors, faisons du cycle de vie de Second Extension Test une forme dans laquelle une instance n'est créée qu'une seule fois.

La source

SecondExtensionTest.java


+ @TestInstance(Lifecycle.PER_CLASS)
public class SecondExtensionTest {

    @RegisterExtension
    FooExtension fooExtension = new FooExtension();

    //Omission
}

résultat

[example.FooExtension@c730b35] created
[example.FooExtension@c730b35] before all
[example.FooExtension@c730b35] before each
test 1
[example.FooExtension@c730b35] after each
[example.FooExtension@c730b35] before each
test 2
[example.FooExtension@c730b35] after each
[example.FooExtension@c730b35] before each
test 3
[example.FooExtension@c730b35] after each
[example.FooExtension@c730b35] after all

L'instance d'extension est partagée. En outre, Avant tout et Après tout fonctionnent maintenant. Si vous enregistrez une extension dans un champ non statique de cette manière, cela dépend naturellement du cycle de vie de la classe de test d'origine.

Si vous le lisez correctement, il sera écrit

https://junit.org/junit5/docs/current/user-guide/#extensions

Recommended Posts

J'ai examiné le cycle de vie de l'extension de JUnit Jupiter
À propos du cycle de vie Android
J'ai lu la source de ArrayList que j'ai lu
J'ai lu la source d'Integer
J'ai lu la source de Long
J'ai lu la source de Short
J'ai lu la source de Byte
J'ai lu la source de String
J'ai examiné le flux de communication TCP avec Spring Integration (édition client)
J'ai examiné le flux de communication TCP avec Spring Integration (édition serveur)
J'ai étudié le traitement interne de Retrofit
[jour: 5] J'ai résumé les bases de Java
Résumer le cycle de vie des objets Java à prendre en compte dans le développement Android
UCP-45060 L'état du cycle de vie n'est pas valide. Vérifiez l'état du pool de connexions universelles
J'ai vérifié la partie de java.net.URL # getPath
J'ai compris les bases de la saisie de caractères
J'ai comparé les caractéristiques de Java et .NET
Écraser le contenu de la configuration avec Spring-boot + JUnit5
Je veux var_dump le contenu de l'intention
J'ai essayé d'utiliser le profileur d'IntelliJ IDEA
J'ai vérifié le nombre de taxis avec Ruby
Essayez Progate Free Edition [Java I]