Перейти к основному содержимому

@Before против @BeforeClass против @BeforeEach против @BeforeAll

· 4 мин. чтения

1. Обзор

В этом коротком руководстве мы собираемся объяснить различия между аннотациями @Before , @BeforeClass , @BeforeEach и @BeforeAll в JUnit 4 и 5 — с практическими примерами их использования.

Мы также кратко рассмотрим их дополнительные аннотации @After .

Начнем с JUnit 4.

2. @До

Методы, помеченные аннотацией @Before , запускаются перед каждым тестом. Это полезно, когда мы хотим выполнить какой-то общий код перед запуском теста.

Давайте инициализируем список и добавим несколько значений:

@RunWith(JUnit4.class)
public class BeforeAndAfterAnnotationsUnitTest {

// ...

private List<String> 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");
}

На этот раз, если мы посмотрим на вывод журнала, мы сможем убедиться, что методы setup и tearDown были запущены только один раз:

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

4. @BeforeEach и @BeforeAll

@BeforeEac h и @BeforeAll — эквиваленты @Before и @BeforeClass в JUnit 5 . Эти аннотации были переименованы с более четкими именами, чтобы избежать путаницы.

Давайте продублируем наши предыдущие классы, используя эти новые аннотации, начиная с аннотаций @BeforeEach и @AfterEach :

class BeforeEachAndAfterEachAnnotationsUnitTest {

// ...

private List<String> 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 в действии:

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 .