Какие аннотации нужны для Mockito и тестового класса, чтобы тесты работали?
Что проверяют
Понимаете ли вы, кто инициализирует поля с @Mock и @InjectMocks, и различаете ли JUnit 4 и JUnit 5. Частый следующий вопрос: почему мок оказался null или почему тест упал с UnnecessaryStubbingException.
Как отвечать
Аннотации Mockito сами ничего не создают, их обрабатывает один из трёх механизмов:
- JUnit 5:
@ExtendWith(MockitoExtension.class)на классе и зависимостьmockito-junit-jupiter. Сейчас это основной вариант; - JUnit 4:
@RunWith(MockitoJUnitRunner.class)или правилоMockitoJUnit.rule(); - вручную:
MockitoAnnotations.openMocks(this)в методе подготовки. Он возвращаетAutoCloseable, который закрывают после теста, а старыйinitMocksустарел. Вместе с расширением или раннером вызывать его не нужно.
Дальше аннотации полей:
@Mock: заглушка, методы возвращают значения по умолчанию, пока не настроитеwhen(...).thenReturn(...);@Spy: обёртка над реальным объектом, вызываются настоящие методы, если их не переопределили;@Captor:ArgumentCaptorдля проверки аргументов вызова;@InjectMocks: создаёт тестируемый объект и внедряет моки через конструктор, а если не вышло, через сеттеры и поля.
Тестовые методы помечаются @Test из org.junit.jupiter.api, подготовка идёт в @BeforeEach. В Spring-тестах бины в контексте подменяет @MockitoBean, а прежний @MockBean в Spring Boot 3.4 объявлен устаревшим.
MockitoExtension по умолчанию работает в режиме strict stubs: неиспользованная заглушка роняет тест. Это полезно, а для исключений есть lenient().
Где спотыкаются
Смешивают поколения: @RunWith вместе с @Test из JUnit 5 или наоборот. Раннер не срабатывает, моки остаются null, а без vintage-движка тесты могут вообще не запуститься.
Надеются, что @InjectMocks сообщит об ошибке. Если подходящего конструктора или поля нет, он молча оставит зависимость пустой, и тест упадёт с NullPointerException в неожиданном месте.
Настраивают шпиона через when(spy.method()). Такой вызов выполняет настоящий метод ещё при настройке, и он может упасть; для @Spy пишут doReturn(value).when(spy).method().