Jak używać ArgumentCaptor do stubbingu?

161

W dokumentacji Mockito i javadocs jest napisane

Zaleca się używanie ArgumentCaptor z weryfikacją, ale nie z stubbingiem.

ale nie rozumiem, w jaki sposób ArgumentCaptor może być używany do stubbingu. Czy ktoś może wyjaśnić powyższe stwierdzenie i pokazać, w jaki sposób ArgumentCaptor może być użyty do stubbingu lub podać link, który pokazuje, jak można to zrobić?

Nie mogę powiedzieć
źródło
1
Super krótkie i przyjemne wyjaśnienie tutaj: dzone.com/articles/…
Benj

Odpowiedzi:

271

Zakładając następującą metodę testowania:

public boolean doSomething(SomeClass arg);

Dokumentacja Mockito mówi, że należy nie używać captor w ten sposób:

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);
assertThat(argumentCaptor.getValue(), equalTo(expected));

Ponieważ możesz po prostu użyć matchera podczas stubbowania:

when(someObject.doSomething(eq(expected))).thenReturn(true);

Ale weryfikacja to inna historia. Jeśli twój test musi upewnić się, że ta metoda została wywołana z określonym argumentem, użyj ArgumentCaptori tak jest w przypadku, dla którego została zaprojektowana:

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));
Rorick
źródło
Dziękuję za odpowiedź. Mam pytanie. W trzecim bloku kodu wiemy, że wartość true jest zwracana tylko wtedy, gdy do funkcji doSomething zostanie przekazane oczekiwanie . Ale kiedy w drugim bloku kodu zwracana jest wartość true? A może w takim przypadku someObject zawsze zwraca true dla someMethod?
Nie mogę powiedzieć,
Hm, wydaje mi się, że miałeś na myśli „Ale kiedy prawda została zwrócona w trzecim bloku kodu?”. W trzecim bloku kodu po prostu nie dbamy o wartość zwracaną i pozwalamy jej być domyślną. W przypadku wartości logicznych tak falsenie jest true.
Rorick
Nie, policzyłem wszystkie szare bloki tła jako bloki kodu. W tym pierwsza wkładka. Odnosiłem
Nie mogę powiedzieć,
O przepraszam. Tak, w tym przypadku prawda zostanie zwrócona zawsze.
Rorick
3
brak pewności, dlaczego „nie używać z stubbingiem” jest prosty powód. dopasowania nie podają nam faktycznego oczekiwanego argumentu (tylko typ) i prowadzi do tego, że testy przechodzą pomyślnie, pomimo argumentów, które mogą być błędne.
dtc
0

Linia

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);

zrobiłby to samo, co

when(someObject.doSomething(Matchers.any())).thenReturn(true);

Tak więc użycie argumentCaptor.capture (), gdy stubbing nie ma wartości dodanej. Użycie Matchers.any () lepiej pokazuje, co naprawdę się dzieje, a tym samym poprawia czytelność. Dzięki argumentCaptor.capture () nie możesz odczytać, które argumenty są naprawdę dopasowane. Zamiast używać any (), możesz użyć bardziej szczegółowych dopasowań, gdy masz więcej informacji (klasa oczekiwanego argumentu), aby ulepszyć swój test.

I jeszcze jeden problem: jeśli używasz argumentCaptor.capture () podczas korkowania, nie jest jasne, ile wartości należy się spodziewać po weryfikacji. Chcemy uchwycić wartość podczas weryfikacji, a nie podczas tworzenia kodu pośredniczącego, ponieważ w tym momencie nie ma jeszcze wartości do przechwycenia. Co więc przechwytuje metoda przechwytywania argumentów podczas krojenia? czy niczego nie rejestruje? Nie mam odpowiedzi na to pytanie. Uważam to za niezdefiniowane zachowanie i nie chcę używać niezdefiniowanego zachowania.

Stefana Mondelaersa
źródło
0

Hipotetycznie, jeśli wyszukiwanie doprowadziło Cię do tego pytania, prawdopodobnie chcesz tego:

doReturn(someReturn).when(someObject).doSomething(argThat(argument -> argument.getName().equals("Bob")));

Czemu? Ponieważ tak jak ja cenisz czas i nie zamierzasz wdrażać .equalstylko ze względu na scenariusz pojedynczego testu.

A 99% testów rozpada się z wartością null zwróconą z Mocka i w rozsądnym projekcie unikniesz zwrotu nullza wszelką cenę, użyj Optionallub przenieś się do Kotlina. Oznacza to, że verifynie musi być używany tak często, a ArgumentCaptors są po prostu zbyt nużące do pisania.

Bakłażan
źródło