0Pricing
Java Academy · Урок

Mockito: продвинутые возможности — перехватчики аргументов и шпионы

Перехватывайте аргументы методов с помощью ArgumentCaptor и частично имитируйте реальные объекты с помощью Mockito.spy.

«Mockito: продвинутые возможности — перехватчики аргументов и шпионы» — бесплатный урок Java Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

ArgumentCaptor: Перехват аргументов методов

ArgumentCaptor перехватывает аргументы, переданные в имитируемый метод, чтобы вы могли проверить их. Это особенно полезно, когда аргумент создается внутри проверяемой системы и недоступен напрямую.

Создание и использование ArgumentCaptor

Создайте объект-перехватчик для типа аргумента, передайте captor.capture() в качестве сопоставителя аргумента в verify(), а затем вызовите captor.getValue(), чтобы получить перехваченный аргумент.

@Test
void sends_correct_email() {
    ArgumentCaptor<EmailMessage> captor = ArgumentCaptor.forClass(EmailMessage.class);
    userService.register(new CreateUserRequest("alice@example.com"));
    verify(emailService).send(captor.capture());
    EmailMessage msg = captor.getValue();
    assertEquals("alice@example.com", msg.getTo());
    assertTrue(msg.getSubject().contains("Welcome"));
}

Аннотация @Captor

Используйте @Captor вместе с @ExtendWith(MockitoExtension.class), чтобы не писать громоздкие вызовы ArgumentCaptor.forClass().

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    @Mock EmailService emailService;
    @Captor ArgumentCaptor<EmailMessage> emailCaptor;
    @Test
    void captures_email() {
        // ...
        verify(emailService).send(emailCaptor.capture());
        assertEquals("Welcome!", emailCaptor.getValue().getSubject());
    }
}

Перехват нескольких вызовов

Используйте captor.getAllValues(), если метод вызывается несколько раз. Метод возвращает список всех перехваченных значений в порядке вызовов.

verify(emailService, times(3)).send(emailCaptor.capture());
List<EmailMessage> messages = emailCaptor.getAllValues();
assertEquals(3, messages.size());
assertEquals("Confirmation", messages.get(0).getSubject());

Mockito-шпионы: частичное имитирование

Mockito.spy() оборачивает реальный объект. Все методы работают как обычно, если явно не настроить их поведение. Используйте шпиона, когда нужно протестировать класс с несколькими сложными для проверки зависимостями, но в основном работающий правильно.

List<String> realList = new ArrayList<>();
List<String> spy = Mockito.spy(realList);
spy.add("hello"); // calls real ArrayList.add()
System.out.println(spy.size()); // 1 — real method called
doReturn(42).when(spy).size(); // stub just size()
System.out.println(spy.size()); // 42 — stubbed

Аннотация @Spy

Используйте @Spy вместе с @ExtendWith(MockitoExtension.class), чтобы создать шпионов. Поле должно быть инициализировано — непосредственно или с помощью @Spy UserService svc = new UserService(repo);.

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
    @Spy
    OrderService orderService = new OrderService(mockRepo, mockEmail);
}

Шпионирование за компонентами Spring с помощью @SpyBean

В тестах Spring Boot @SpyBean оборачивает существующий компонент Spring в шпиона Mockito — сохраняется реальное поведение, если его не настроить.

@SpringBootTest
class IntegrationTest {
    @SpyBean EmailService emailService;
    @Test
    void order_sends_email() {
        orderService.placeOrder(cart);
        verify(emailService).sendConfirmation(any());
    }
}

doReturn вместо when().thenReturn() для шпионов

Для шпионов используйте doReturn(value).when(spy).method() вместо when(spy.method()).thenReturn(value). Форма when(spy.method()) фактически вызывает реальный метод, что может привести к побочным эффектам.

// Correct for spies:
doReturn(List.of()).when(spy).findAll();
// WRONG for spies — calls real findAll() first:
when(spy.findAll()).thenReturn(List.of()); // real method called!

Проверка отсутствия взаимодействий

Используйте verifyNoInteractions(mock), чтобы проверить, что имитируемый объект ни разу не вызывался, а после всех ожидаемых вызовов применяйте verifyNoMoreInteractions(mock), чтобы обнаружить неожиданные вызовы.

verifyNoInteractions(emailService); // never called
verify(repo).save(any());
verifyNoMoreInteractions(repo); // save() was the only interaction

Проверка порядка вызовов с InOrder

Используйте InOrder, чтобы проверить, что методы имитируемого объекта вызывались в определенном порядке.

InOrder inOrder = inOrder(repo, emailService);
inOrder.verify(repo).save(any());
inOrder.verify(emailService).send(any()); // save happened BEFORE send

Сопоставители аргументов

Сочетайте перехватчики с сопоставителями: any(), eq(), anyString(), argThat(predicate). Если для одного аргумента используется сопоставитель, сопоставители должны использоваться для всех аргументов.

verify(repo).save(argThat(user ->
    user.getEmail().endsWith("@example.com") &&
    user.getStatus() == UserStatus.ACTIVE));

Быстрая проверка

Почему при настройке шпиона следует использовать doReturn вместо when().thenReturn()?

Итоги

ArgumentCaptor перехватывает аргументы для проверки после вызова. Шпионы оборачивают реальные объекты и делегируют им вызовы, если поведение не настроено. Для шпионов используйте doReturn. Для интеграционных тестов Spring используйте @SpyBean. Проверяйте порядок вызовов с помощью InOrder.

Часто задаваемые вопросы

Урок «Mockito: продвинутые возможности — перехватчики аргументов и шпионы» бесплатный?

Да — полный текст урока «Mockito: продвинутые возможности — перехватчики аргументов и шпионы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Mockito: продвинутые возможности — перехватчики аргументов и шпионы»?

Перехватывайте аргументы методов с помощью ArgumentCaptor и частично имитируйте реальные объекты с помощью Mockito.spy. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Mockito: продвинутые возможности — перехватчики аргументов и шпионы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Параметризованные тесты с @CsvSource и @MethodSource
  2. Mockito: продвинутые возможности — перехватчики аргументов и шпионы
  3. Срезы тестирования Spring Boot: @WebMvcTest и @DataJpaTest
  4. Testcontainers: интеграционные тесты с реальной базой данных
← Назад к Java Academy