Как проходит жизненный цикл теста с аннотациями @Test, @Before, @After в Java
Что проверяют
Знаете ли вы порядок вызовов и то, что тестовый объект создаётся заново для каждого теста. Отдельно смотрят, различаете ли вы JUnit 4 и JUnit Jupiter: аннотации @Before и @After из вопроса относятся к четвёртой версии. Следом обычно спрашивают про @BeforeClass и про то, что будет, если тест упал.
Как отвечать
Для одного тестового метода в JUnit 4 порядок такой:
- конструктор класса: JUnit 4 создаёт новый экземпляр тестового класса для каждого метода
@Test, поэтому поля не переносят состояние между тестами; @Before: подготовка перед каждым тестом, например создание объекта под тест и моков;@Test: сам тест. Ожидаемое исключение проверяют через@Test(expected = ...)илиassertThrows(с версии 4.13), таймаут задаётся параметромtimeout;@After: очистка после каждого теста. Выполняется, даже если тест упал.
Вокруг всего класса работают @BeforeClass и @AfterClass. Методы с ними обязаны быть static и выполняются один раз, поэтому подходят для дорогих ресурсов вроде подъёма тестовой базы. При наследовании @Before родителя идёт раньше дочернего, а @After дочернего раньше родительского.
В JUnit Jupiter (JUnit 5 и новее) те же роли называются @BeforeEach, @AfterEach, @BeforeAll, @AfterAll. @BeforeAll тоже статический, если не включить @TestInstance(Lifecycle.PER_CLASS): тогда экземпляр класса один на все тесты, методы могут быть нестатическими, но поля начинают делить состояние.
Порядок самих тестовых методов в обеих версиях детерминирован, но намеренно неочевиден, полагаться на него нельзя. Если порядок важен, тесты связаны между собой; зафиксировать его можно через @FixMethodOrder или @TestMethodOrder.
Где спотыкаются
Смешивают версии: ставят @Before из org.junit в класс с @Test из org.junit.jupiter.api. Jupiter такую аннотацию не видит, и подготовка молча не выполняется.
Считают, что поле, изменённое в одном тесте, доступно в следующем. При жизненном цикле по умолчанию каждый тест получает свежий экземпляр.
Кладут тяжёлую инициализацию в @Before или @BeforeEach, и тестовая база поднимается перед каждым из сотни тестов вместо одного раза на класс.