@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll

1. Introduction

Dans ce court tutoriel, nous allons expliquer les différences entre les annotations @Before , @BeforeClass , @BeforeEach et @BeforeAll dans JUnit 4 et 5 - avec des exemples pratiques de leur utilisation.

Nous couvrirons également brièvement leurs @After annotations complémentaires.

Commençons par JUnit 4.

2. @Before

Les méthodes annotées avec l' annotation @Before sont exécutées avant chaque test. Ceci est utile lorsque nous voulons exécuter du code commun avant d'exécuter un test.

Voyons un exemple où nous initialisons une liste et ajoutons quelques valeurs:

@RunWith(JUnit4.class) public class BeforeAndAfterAnnotationsUnitTest { // ... private List list; @Before public void init() { LOG.info("startup"); list = new ArrayList(Arrays.asList("test1", "test2")); } @After public void teardown() { LOG.info("teardown"); list.clear(); } }

Notez que nous avons également ajouté une autre méthode annotée avec @After afin d'effacer la liste après l'exécution de chaque test.

Après cela, ajoutons quelques tests pour vérifier la taille de notre liste:

@Test public void whenCheckingListSize_thenSizeEqualsToInit() { LOG.info("executing test"); assertEquals(2, list.size()); list.add("another test"); } @Test public void whenCheckingListSizeAgain_thenSizeEqualsToInit() { LOG.info("executing another test"); assertEquals(2, list.size()); list.add("yet another test"); }

Dans ce cas, il est crucial de s'assurer que l'environnement de test est correctement configuré avant d'exécuter chaque test car la liste est modifiée à chaque exécution de test.

Si nous regardons la sortie du journal, nous pouvons vérifier que les méthodes init et teardown ont été exécutées une fois par test:

... startup ... executing another test ... teardown ... startup ... executing test ... teardown

3. @BeforeClass

Lorsque nous voulons exécuter une opération commune coûteuse avant chaque test, il est préférable de ne l'exécuter qu'une seule fois avant d'exécuter tous les tests à l'aide de @BeforeClass . Quelques exemples d'opérations coûteuses courantes sont la création d'une connexion à une base de données ou le démarrage d'un serveur.

Créons une classe de test simple qui simule la création d'une connexion à une base de données:

@RunWith(JUnit4.class) public class BeforeClassAndAfterClassAnnotationsUnitTest { // ... @BeforeClass public static void setup() { LOG.info("startup - creating DB connection"); } @AfterClass public static void tearDown() { LOG.info("closing DB connection"); } }

Notez que ces méthodes doivent être statiques , elles seront donc exécutées avant d'exécuter les tests de la classe.

Comme nous l'avons fait auparavant, ajoutons également quelques tests simples:

@Test public void simpleTest() { LOG.info("simple test"); } @Test public void anotherSimpleTest() { LOG.info("another simple test"); }

Cette fois, si nous regardons la sortie du journal, nous pouvons vérifier que les méthodes setup et tearDown n'ont été exécutées qu'une seule fois:

... startup - creating DB connection ... simple test ... another simple test ... closing DB connection

4. @BeforeEach et @BeforeAll

@BeforeEac h et @BeforeAll sont les équivalents JUnit 5 de @Before et @BeforeClass . Ces annotations ont été renommées avec des noms plus clairs pour éviter toute confusion.

Reproduisons nos classes précédentes en utilisant ces nouvelles annotations, en commençant par les annotations @BeforeEach et @AfterEach :

@RunWith(JUnitPlatform.class) class BeforeEachAndAfterEachAnnotationsUnitTest { // ... private List list; @BeforeEach void init() { LOG.info("startup"); list = new ArrayList(Arrays.asList("test1", "test2")); } @AfterEach void teardown() { LOG.info("teardown"); list.clear(); } // ... }

Si nous vérifions les journaux, nous pouvons confirmer que cela fonctionne de la même manière qu'avec les annotations @Before et @After :

... startup ... executing another test ... teardown ... startup ... executing test ... teardown

Enfin, faisons de même avec l'autre classe de test pour voir les annotations @BeforeAll et @AfterAll en action:

@RunWith(JUnitPlatform.class) public class BeforeAllAndAfterAllAnnotationsUnitTest { // ... @BeforeAll public static void setup() { LOG.info("startup - creating DB connection"); } @AfterAll public static void tearDown() { LOG.info("closing DB connection"); } // ... }

Et la sortie est la même qu'avec l'ancienne annotation:

... startup - creating DB connection ... simple test ... another simple test ... closing DB connection

5. Conclusion

Dans cet article, nous avons montré les différences entre les annotations @Before , @BeforeClass , @BeforeEach et @BeforeAll dans JUnit et quand chacune d'elles doit être utilisée.

Comme toujours, le code source complet des exemples est disponible à l'adresse over sur GitHub.