@Before срещу @BeforeClass срещу @BeforeEach срещу @BeforeAll

1. Въведение

В този кратък урок ще обясним разликите между поясненията @Before , @BeforeClass , @BeforeEach и @BeforeAll в JUnit 4 и 5 - с практически примери как да ги използваме.

Също така ще разгледаме накратко техните @ След допълнителни пояснения.

Нека започнем с JUnit 4.

2. @ Преди това

Методите, анотирани с анотацията @Before, се изпълняват преди всеки тест. Това е полезно, когато искаме да изпълним някакъв общ код, преди да стартираме тест.

Нека да видим пример, в който инициализираме списък и добавяме някои стойности:

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

Забележете, че добавихме и друг метод, коментиран с @After, за да изчистим списъка след изпълнението на всеки тест.

След това нека добавим няколко теста, за да проверим размера на нашия списък:

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

В този случай е изключително важно да се уверите, че тестовата среда е правилно настроена, преди да стартирате всеки тест, тъй като списъкът се променя по време на всяко изпълнение на теста.

Ако разгледаме изхода на регистрационния файл, можем да проверим дали методите init и teardown са изпълнени веднъж на тест:

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

3. @BeforeClass

Когато искаме да изпълним скъпа обща операция преди всеки тест, за предпочитане е да я изпълним само веднъж, преди да стартираме всички тестове с помощта на @BeforeClass . Някои примери за често срещани скъпи операции са създаването на връзка с база данни или стартирането на сървър.

Нека създадем прост тестов клас, който симулира създаването на връзка с база данни:

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

Забележете, че тези методи трябва да са статични , така че те ще бъдат изпълнени преди да стартирате тестовете на класа.

Както направихме преди, нека добавим и няколко прости теста:

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

Този път, ако разгледаме изхода на журнала, можем да проверим дали методите за настройка и tearDown са изпълнени само веднъж:

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

4. @BeforeEach и @BeforeAll

@BeforeEac h и @BeforeAll са еквивалентите на JUnit 5 на @Before и @BeforeClass . Тези анотации бяха преименувани с по-ясни имена, за да се избегне объркване.

Нека дублираме предишните си класове, като използваме тези нови анотации, като започнем с анотациите @BeforeEach и @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(); } // ... }

Ако ние проверяваме трупи, ние може да потвърди, че работи по същия начин, както с @Before и @After пояснителните бележки:

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

И накрая, нека направим същото с другия тестов клас, за да видим @BeforeAll и @AfterAll анотациите в действие:

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

И изходът е същият като при старата анотация:

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

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

В тази статия показахме разликите между анотациите @Before , @BeforeClass , @BeforeEach и @BeforeAll в JUnit и кога всеки от тях трябва да се използва.

Както винаги, пълният изходен код на примерите е достъпен в GitHub.