@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll

@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll

1. Einführung

In diesem kurzen Tutorial erklären wir die Unterschiede zwischen den Anmerkungen@Before,@BeforeClass,@BeforeEach und@BeforeAll in JUnit 4 und 5 - mit praktischen Beispielen dafür um sie zu benutzen.

Wir werden auch kurz auf die ergänzenden Anmerkungen zu@Aftereingehen.

Beginnen wir mit JUnit 4.

2. @Before

Methods annotated with the @Before annotation are executed before each test. Dies ist nützlich, wenn Sie vor dem Ausführen eines Tests allgemeinen Code ausführen möchten.

Sehen wir uns ein Beispiel an, in dem wir eine Liste initialisieren und einige Werte hinzufügen:

@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 finalize() {
        LOG.info("finalize");
        list.clear();
    }
}

Beachten Sie, dass wir auch eine andere Methode hinzugefügt haben, die mit@After versehen ist, um die Liste nach der Ausführung jedes Tests zu löschen.

Fügen Sie anschließend einige Tests hinzu, um die Größe unserer Liste zu überprüfen:

@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");
}

In diesem Fallit’s crucial to make sure that test environment is properly set up before running each test, da die Liste bei jeder Testausführung geändert wird.

Wenn wir uns die Protokollausgabe ansehen, können wir überprüfen, ob die Methodeninit undfinalize einmal pro Test ausgeführt wurden:

... startup
... executing another test
... finalize
... startup
... executing test
... finalize

3. @BeforeClass

Wenn wir vor jedem Test eine teure gemeinsame Operation ausführen möchten,it’s preferable to execute it only once before running all tests using @BeforeClass. Einige Beispiele für häufig vorkommende teure Vorgänge sind das Herstellen einer Datenbankverbindung oder das Starten eines Servers.

Erstellen wir eine einfache Testklasse, die das Erstellen einer Datenbankverbindung simuliert:

@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");
    }
}

Beachten Sie, dassthese methods have to be static sind, damit sie ausgeführt werden, bevor die Tests der Klasse ausgeführt werden.

Fügen wir wie zuvor auch einige einfache Tests hinzu:

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

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

Wenn wir uns diesmal die Protokollausgabe ansehen, können wir überprüfen, ob die Methodensetup undtearDown nur einmal ausgeführt wurden:

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

4. @BeforeEach und@BeforeAll

@BeforeEach and @BeforeAll are the JUnit 5 equivalents of @Before and @BeforeClass. Diese Anmerkungen wurden mit klareren Namen umbenannt, um Verwechslungen zu vermeiden.

Lassen Sie uns unsere vorherigen Klassen mit diesen neuen Annotationen duplizieren, beginnend mit den Annotationen@BeforeEach und@AfterEach:

@RunWith(JUnitPlatform.class)
class BeforeEachAndAfterEachAnnotationsUnitTest {

    // ...

    private List list;

    @BeforeEach
    void init() {
        LOG.info("startup");
        list = new ArrayList<>(Arrays.asList("test1", "test2"));
    }

    @AfterEach
    void finalize() {
        LOG.info("finalize");
        list.clear();
    }

    // ...
}

Wenn wir Protokolle überprüfen, können wir bestätigen, dass dies genauso funktioniert wie bei den Anmerkungen@Before und@After:

... startup
... executing another test
... finalize
... startup
... executing test
... finalize

Lassen Sie uns abschließend dasselbe mit der anderen Testklasse tun, um die Anmerkungen@BeforeAll und@AfterAllin Aktion zu sehen:

@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");
    }

    // ...
}

Und die Ausgabe ist die gleiche wie bei der alten Annotation:

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

5. Fazit

In diesem Artikel haben wir die Unterschiede zwischen den Anmerkungen@Before,@BeforeClass,@BeforeEach und@BeforeAll in JUnit gezeigt und wann sie jeweils verwendet werden sollten.

Wie immer ist der vollständige Quellcode der Beispieleover on GitHub verfügbar.