@ Перед тем как @BeforeClass против @BeforeEach против @BeforeAll

@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll

1. Вступление

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

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

Начнем с JUnit 4.

2. @Beforeс

Methods annotated with the @Before annotation are executed before each test. Это полезно, когда мы хотим выполнить некоторый общий код перед запуском теста.

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

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

Обратите внимание, что мы также добавили еще один метод, помеченный@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");
}

В данном случаеit’s crucial to make sure that test environment is properly set up before running each test, поскольку список изменяется при каждом выполнении теста.

Если мы посмотрим на вывод журнала, мы сможем убедиться, что методыinit иfinalize выполнялись один раз за тест:

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

3. @BeforeClassс

Когда мы хотим выполнить дорогостоящую обычную операцию перед каждым тестом,it’s preferable to execute it only once before running all tests using @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");
    }
}

Обратите внимание наthese methods have to be static, поэтому они будут выполнены перед запуском тестов класса.

Как и раньше, давайте также добавим несколько простых тестов:

@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

@BeforeEach and @BeforeAll are the JUnit 5 equivalents of @Before and @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 finalize() {
        LOG.info("finalize");
        list.clear();
    }

    // ...
}

Если мы проверим журналы, мы можем подтвердить, что он работает так же, как и с аннотациями@Before и@After:

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

Наконец, давайте сделаем то же самое с другим тестовым классом, чтобы увидеть аннотации@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, и когда следует использовать каждую из них.

Как всегда, доступен полный исходный код примеровover on GitHub.