Java Academy · Lekcja

Mockito zaawansowane: przechwytywanie argumentów i szpiegi

Proszę przechwytywać argumenty metod za pomocą ArgumentCaptor i częściowo mockować rzeczywiste obiekty przez Mockito.spy.

Lekcja 2 z 413 kroki

Mockito zaawansowane: przechwytywanie argumentów i szpiegi to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.

ArgumentCaptor: przechwytywanie argumentów metod

ArgumentCaptor przechwytuje argumenty przekazane do mockowanej metody, dzięki czemu można je sprawdzić. Jest przydatny, gdy argument jest tworzony wewnątrz testowanego systemu i nie można uzyskać do niego bezpośredniego dostępu.

Tworzenie i używanie ArgumentCaptor

Utwórz captor dla typu argumentu, przekaż captor.capture() jako matcher argumentu w verify(), a następnie wywołaj captor.getValue(), aby pobrać przechwycony argument.

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

Adnotacja @Captor

Używaj @Captor razem z @ExtendWith(MockitoExtension.class), aby uniknąć rozwlekłych wywołań 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());
    }
}

Przechwytywanie wielu wywołań

Używaj captor.getAllValues(), gdy metoda jest wywoływana wiele razy. Zwraca ono listę wszystkich przechwyconych wartości w kolejności wywołań.

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

Szpiegi Mockito: częściowe mockowanie

Mockito.spy() opakowuje rzeczywisty obiekt. Wszystkie metody działają normalnie, chyba że jawnie je zamockujesz. Używaj tego rozwiązania, gdy trzeba przetestować klasę, która ma pewne trudne do testowania zależności, ale w większości działa poprawnie.

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

Adnotacja @Spy

Używaj @Spy razem z @ExtendWith(MockitoExtension.class), aby tworzyć szpiegi. Pole musi zostać zainicjalizowane (bezpośrednio lub za pomocą @Spy UserService svc = new UserService(repo);).

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

Szpiegowanie beanów Spring za pomocą @SpyBean

W testach Spring Boot adnotacja @SpyBean opakowuje istniejący bean Spring w szpiega Mockito — zachowuje on rzeczywiste działanie, chyba że zostanie zamockowany. Jest używana razem z @SpringBootTest.

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

doReturn a when().thenReturn() w przypadku szpiegów

W przypadku szpiegów używaj doReturn(value).when(spy).method() zamiast when(spy.method()).thenReturn(value). Postać when(spy.method()) faktycznie wywołuje rzeczywistą metodę, co może powodować skutki uboczne.

// 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!

Sprawdzanie braku interakcji

Używaj verifyNoInteractions(mock), aby sprawdzić, czy mock nigdy nie został wywołany, oraz verifyNoMoreInteractions(mock) po wszystkich oczekiwanych wywołaniach, aby wykrywać nieoczekiwane interakcje.

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

Sprawdzanie kolejności za pomocą InOrder

Używaj InOrder, aby sprawdzać, czy mockowane metody zostały wywołane w określonej kolejności.

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

Matchery argumentów

Łącz captory z matcherami: any(), eq(), anyString(), argThat(predicate). Jeśli jeden z argumentów używa matchera, wszystkie argumenty muszą używać matcherów.

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

Szybkie sprawdzenie

Dlaczego podczas mockowania szpiega należy używać doReturn zamiast when().thenReturn()?

Podsumowanie

ArgumentCaptor przechwytuje argumenty, aby można je było sprawdzić po wywołaniu. Szpiegi opakowują rzeczywiste obiekty i przekazują do nich wywołania, chyba że metody zostaną zamockowane. Używaj doReturn w przypadku szpiegów. Używaj @SpyBean w testach integracyjnych Spring. Sprawdzaj kolejność wywołań za pomocą InOrder.

Bezpłatny start

Ucz się Java dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
104
Lekcje
374

Często zadawane pytania

Czy lekcja „Mockito zaawansowane: przechwytywanie argumentów i szpiegi” jest bezpłatna?

Tak — pełny tekst „Mockito zaawansowane: przechwytywanie argumentów i szpiegi” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Mockito zaawansowane: przechwytywanie argumentów i szpiegi”?

Proszę przechwytywać argumenty metod za pomocą ArgumentCaptor i częściowo mockować rzeczywiste obiekty przez Mockito.spy. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Java Academy?

Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Mockito zaawansowane: przechwytywanie argumentów i szpiegi”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?

Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Testy parametryzowane za pomocą @CsvSource i @MethodSource
  2. Mockito zaawansowane: przechwytywanie argumentów i szpiegi
  3. Wycinanie testów Spring Boot: @WebMvcTest i @DataJpaTest
  4. Testcontainers: integracyjne testy z rzeczywistą bazą danych
← Powrót do Java Academy