mockito wywołania zwrotne i pobieranie wartości argumentów


88

Nie mam szczęścia, aby Mockito przechwytywał wartości argumentów funkcji! Kpię z indeksu wyszukiwarki i zamiast budować indeks, używam tylko skrótu.

// Fake index for solr
Hashmap<Integer,Document> fakeIndex;

// Add a document 666 to the fakeIndex
SolrIndexReader reader = Mockito.mock(SolrIndexReader.class);

// Give the reader access to the fake index
Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))

Nie mogę używać dowolnych argumentów, ponieważ testuję wyniki zapytań (tj. Które dokumenty zwracają). Podobnie nie chcę określać konkretnej wartości i mieć wiersz dla każdego dokumentu!

Mockito.when(reader.document(0)).thenReturn(document(fakeIndex(0))
Mockito.when(reader.document(1)).thenReturn(document(fakeIndex(1))
....
Mockito.when(reader.document(n)).thenReturn(document(fakeIndex(n))

Przejrzałem sekcję wywołań zwrotnych na stronie Korzystanie z Mockito . Niestety, to nie jest Java i nie mogłem uzyskać własnej interpretacji tego do pracy w Javie.

EDYCJA (dla wyjaśnienia): Jak zmusić Mockito do przechwycenia argumentu X i przekazania go do mojej funkcji? Chcę dokładnej wartości (lub ref) X przekazanej do funkcji.

Nie chcę wyliczać wszystkich przypadków, a dowolny argument nie zadziała, ponieważ testuję różne wyniki dla różnych zapytań.

Mówi strona Mockito

val mockedList = mock[List[String]]
mockedList.get(anyInt) answers { i => "The parameter is " + i.toString } 

To nie jest java i nie wiem, jak przetłumaczyć na język java ani przekazać tego, co się stało, do funkcji.


Nie jestem pewien, czy dokładnie rozumiem, co ci się nie udaje. Twoje wywołanie Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))powinno ustawić dla ciebie obiekt pozorowany. Co się dzieje, kiedy dzwonisz reader.document(666)?
dużą zawartością kofeiny

666 działa dobrze. Chciałbym jednak móc przekazać konkretną liczbę X i uzyskać wynik fakeIndex (X). Mam dużą liczbę potencjalnych dokumentów do przetestowania pod kątem zapytań i nie chcę wprowadzać ich wszystkich.
nflacco

Odpowiedzi:


103

Nigdy nie korzystałem z Mockito, ale chcę się uczyć, więc proszę bardzo. Jeśli ktoś mniej wiedzący ode mnie odpowie, najpierw wypróbuj jego odpowiedź!

Mockito.when(reader.document(anyInt())).thenAnswer(new Answer() {
 public Object answer(InvocationOnMock invocation) {
     Object[] args = invocation.getArguments();
     Object mock = invocation.getMock();
     return document(fakeIndex((int)(Integer)args[0]));
     }
 });

2
Właśnie zauważyłem link po prawej stronie do Mockito: Jak sprawić, by metoda zwracała argument, który został do niej przekazany . Wygląda na to, że jestem blisko, jeśli nie na miejscu.
Ed Staub,

silna reputacja użytkownika (666) z oryginalną korelacją pytań! To działało bardzo dobrze. Jedyna zmiana, którą wprowadziłem, aby uzyskać kompilację, została upubliczniona przed odpowiedzią obiektu (wywołanie InvocationOnMock) ....
nflacco

54

Sprawdź ArgumentCaptors:

https://site.mockito.org/javadoc/current/org/mockito/ArgumentCaptor.html

ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
Mockito.when(reader.document(argument.capture())).thenAnswer(
  new Answer() {
    Object answer(InvocationOnMock invocation) {
      return document(argument.getValue());
    }
  });

3
Wow, nie wiedziałem, że możesz użyć ArgumentCaptors do zarostu. W tym linku jest jednak wielkie ostrzeżenie na ten temat. Postępuj ostrożnie.
einnocenty

3
Tak, masz rację. Captors powinien być używany tylko z weryfikacją.
kwalifikacyjny mecz

41

Możesz chcieć użyć weryfikacji () w połączeniu z ArgumentCaptor, aby zapewnić wykonanie w teście i ArgumentCaptor, aby ocenić argumenty:

ArgumentCaptor<Document> argument = ArgumentCaptor.forClass(Document.class);
verify(reader).document(argument.capture());
assertEquals(*expected value here*, argument.getValue());

Wartość argumentu jest oczywiście dostępna poprzez argument.getValue () w celu dalszej manipulacji / sprawdzania lub czegokolwiek innego, co chcesz zrobić.


2
najlepsza odpowiedź: prosta, łatwa do zrozumienia
Radu Cugut

Nie odpowiada na pytanie. Pytanie dotyczy Mockito. Kiedy i nie weryfikuj.
seBaka28

@ seBaka28 najlepszym sposobem uzyskiwania argumentów jest przechwytywanie argumentów. Zdecydowanie zaleca się używanie ArgumentCaptors z weryfikacją przez autorów Mockito, dlatego chciałem udzielić pełnej odpowiedzi perspektywicznej. jeśli zdecydujesz się ich nie używać, to jest twój wybór, ale nie jest to zalecane. EDYCJA: Nie rozumiem, jak to usprawiedliwia głos przeciw, ale jest to również Twój wybór.
fl0w

1
Ponieważ nie odpowiada na pytanie. Tak, ArgumentCaptor jest świetny, gdy chcesz przechwycić argument, ale nie możesz go używać w połączeniu z when (...). ThenReturn (), co jest tym, co próbuje zrobić OP: Na podstawie określonego parametru, fałszywa usługa ma zwrócić określony obiekt.
seBaka28

1
@YuraHoy, który jest standardowym komunikatem o błędzie, gdy używasz weryfikacji, a obiekt lub metoda jest wywoływana częściej niż powiedziałeś, że weryfikujesz, aby się spodziewać. Możesz zmienić liczbę oczekiwań, dodając argument times (n) w następujący sposób: verify (reader, times (5)) - to oczekiwałoby 5 interakcji. Więcej informacji można znaleźć na stronie: baeldung.com/mockito-verify
fl0w

13

W Javie 8 może to wyglądać mniej więcej tak:

Mockito.when(reader.document(anyInt())).thenAnswer(
  (InvocationOnMock invocation) -> document(invocation.getArguments()[0]));

Zakładam, że documentto mapa.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.