Что делает аннотация @ExtendWith в JUnit 5
Что проверяют
Знаете ли вы модель расширений JUnit 5 и понимаете ли, что она заменила собой @RunWith и правила из четвёртой версии. Вопрос почти всегда переходит в Mockito и Spring, потому что именно оттуда расширения приходят в реальные проекты.
Как отвечать
@ExtendWith декларативно подключает расширение к тестовому классу или методу. Расширение это класс, реализующий интерфейсы точек расширения: BeforeAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver, TestExecutionExceptionHandler и другие. Движок вызывает их в нужные моменты жизненного цикла теста.
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock OrderRepository repository;
@InjectMocks OrderService service;
}Ключевое отличие от JUnit 4: там на класс приходился ровно один Runner, и совместить Spring с Mockito без костылей не выходило. @ExtendWith повторяемая, расширений можно навесить сколько нужно.
Что стоит назвать дополнительно:
@RegisterExtensionна поле нужен, когда расширение настраивается программно, с параметрами;- аннотации вроде
@SpringBootTestсами помечены@ExtendWith(SpringExtension.class), дублировать её не надо; ParameterResolverобъясняет, откуда в тестовый метод прилетают аргументы вродеTestInfo;MockitoExtensionвключает строгую проверку заглушек, и неиспользованная заглушка роняет тест.
Где спотыкаются
Дублируют @ExtendWith(SpringExtension.class) рядом с @SpringBootTest, считая, что без этого контекст не поднимется. Вреда нет, но композицию аннотаций человек явно не понимает.
Второе: путают расширение с обычным @BeforeEach. Метод живёт в одном классе, расширение переиспользуется между классами и вмешивается там, куда @BeforeEach не дотягивается: подстановка параметров, перехват исключений, условное отключение теста.
Третье: тянут в проект vintage-движок, продолжают писать @RunWith с правилами и добавляют рядом @ExtendWith. На одном классе это не работает: аннотации четвёртой версии обрабатывает другой движок, и половина настройки молча не применяется.