Jaka jest różnica między kpiną a szpiegowaniem podczas korzystania z Mockito?
137
Jaki byłby przypadek użycia szpiega Mockito?
Wydaje mi się, że każdy przypadek użycia szpiega można obsłużyć z makietą, używając callRealMethod.
Jedyną różnicą, jaką widzę, jest to, że jeśli chcesz, aby większość wywołań metod była rzeczywista, oszczędza kilka linii kodu, aby użyć makiety zamiast szpiega. Czy to wszystko, czy brakuje mi szerszego obrazu?
Wreszcie, po wielu wewnętrznych debatach i dyskusjach na liście mailingowej, do Mockito dodano częściowe pozorowane wsparcie. Wcześniej rozważaliśmy częściowe kpiny jako zapachy kodu. Jednak znaleźliśmy uzasadniony przypadek użycia częściowych prób.
Przed wydaniem 1.8 spy () nie produkował rzeczywistych częściowych prób i było to mylące dla niektórych użytkowników. Przeczytaj więcej o szpiegowaniu: tutaj lub w javadoc dla metody spy (Object).
callRealMethod()został wprowadzony później spy(), ale oczywiście spy () tam pozostawiono, aby zapewnić wsteczną kompatybilność.
W przeciwnym razie masz rację: wszystkie metody szpiega są prawdziwe, chyba że zostaną skrócone. Wszystkie metody makiety są odrzucane, chyba że callRealMethod()zostanie wywołane. Generalnie wolałbym używać callRealMethod(), ponieważ nie zmusza mnie to do używania doXxx().when()idiomu zamiast tradycyjnegowhen().thenXxx()
Problem z preferowaniem makiety zamiast szpiegowania w tych przypadkach polega na tym, że klasa używa elementu członkowskiego, który nie jest do niej wstrzyknięty (ale zainicjowany lokalnie) i jest później używany przez metodę „real”; w makiecie element członkowski zostanie zainicjowany z domyślną wartością Java, co może spowodować nieprawidłowe zachowanie lub nawet wyjątek NullPointerException. Sposobem na to jest dodanie metody „init”, a następnie „naprawdę” wywołanie jej, ale wydaje mi się to trochę przesadą.
Eyal Roth
Z dokumentu: „Ze szpiegów należy korzystać ostrożnie i okazjonalnie, na przykład podczas korzystania ze starszego kodu”. Przestrzeń do testów jednostkowych cierpi na zbyt wiele sposobów robienia tego samego.
gdbj
89
Różnica między Szpiegiem a Mockiem
Kiedy Mockito tworzy makietę - robi to z klasy typu, a nie z rzeczywistej instancji. Makieta po prostu tworzy szkieletową instancję klasy Class, w całości przystosowaną do śledzenia interakcji z nią. Z drugiej strony szpieg zapakuje istniejącą instancję. Będzie nadal zachowywał się w taki sam sposób, jak normalna instancja - jedyną różnicą jest to, że będzie ona również wyposażona w narzędzia do śledzenia wszystkich interakcji z nią.
W poniższym przykładzie - tworzymy makietę klasy ArrayList:
Jak widać - dodanie elementu do makiety w rzeczywistości niczego nie dodaje - po prostu wywołuje metodę bez żadnego innego efektu ubocznego. Z drugiej strony szpieg zachowa się inaczej - faktycznie wywoła rzeczywistą implementację metody add i doda element do listy bazowej:
Tutaj możemy z pewnością powiedzieć, że prawdziwa wewnętrzna metoda obiektu została wywołana, ponieważ wywołanie metody size () daje rozmiar 1, ale ta metoda size () nie została wyszydzona! Skąd więc pochodzę? Wewnętrzna metoda real size () jest wywoływana, ponieważ size () nie jest wyszydzana (ani ukryta), dlatego możemy powiedzieć, że wpis został dodany do rzeczywistego obiektu.
W pierwszym przykładzie, dlaczego mockedList.size()zwraca, 0jeśli ta metoda również nie została usunięta? Czy to tylko wartość domyślna, biorąc pod uwagę zwracany typ metody?
Mike
@mike: mockedList.size()zwraca intwartość domyślną int0 w Javie. Jeśli spróbujesz wykonać assertEquals(0, mockedList.size());później mockedList.clear();, wynik pozostanie taki sam.
realPK
2
Ta odpowiedź jest dobrze i prosto napisana i pomogła mi w końcu zrozumieć różnicę między symulacją a szpiegiem. Niezłe.
PesaThe
38
Jeśli istnieje obiekt z 8 metodami i masz test, w którym chcesz wywołać 7 prawdziwych metod, a jedną z nich usunąć, masz dwie opcje:
Używając makiety, musiałbyś go ustawić przez wywołanie 7 callRealMethod i odcięcie jednej metody
Używając a spy, musisz go ustawić, odrzucając jedną metodę
Oficjalna dokumentacja na doCallRealMethodzaleca stosowanie szpiegiem częściowych mocks.
Zobacz także javadoc spy (Object), aby dowiedzieć się więcej o częściowych mockach. Mockito.spy () to zalecany sposób tworzenia częściowych mocków. Powodem jest to, że gwarantuje wywołanie prawdziwych metod przeciwko poprawnie skonstruowanemu obiektowi, ponieważ jesteś odpowiedzialny za skonstruowanie obiektu przekazanego do metody spy ().
Różnica między Szpiegiem a Mockiem
Kiedy Mockito tworzy makietę - robi to z klasy typu, a nie z rzeczywistej instancji. Makieta po prostu tworzy szkieletową instancję klasy Class, w całości przystosowaną do śledzenia interakcji z nią. Z drugiej strony szpieg zapakuje istniejącą instancję. Będzie nadal zachowywał się w taki sam sposób, jak normalna instancja - jedyną różnicą jest to, że będzie ona również wyposażona w narzędzia do śledzenia wszystkich interakcji z nią.
W poniższym przykładzie - tworzymy makietę klasy ArrayList:
Jak widać - dodanie elementu do makiety w rzeczywistości niczego nie dodaje - po prostu wywołuje metodę bez żadnego innego efektu ubocznego. Z drugiej strony szpieg zachowa się inaczej - faktycznie wywoła rzeczywistą implementację metody add i doda element do listy bazowej:
Tutaj możemy z pewnością powiedzieć, że prawdziwa wewnętrzna metoda obiektu została wywołana, ponieważ wywołanie metody size () daje rozmiar 1, ale ta metoda size () nie została wyszydzona! Skąd więc pochodzę? Wewnętrzna metoda real size () jest wywoływana, ponieważ size () nie jest wyszydzana (ani ukryta), dlatego możemy powiedzieć, że wpis został dodany do rzeczywistego obiektu.
Źródło: http://www.baeldung.com/mockito-spy + notatki własne.
źródło
mockedList.size()
zwraca,0
jeśli ta metoda również nie została usunięta? Czy to tylko wartość domyślna, biorąc pod uwagę zwracany typ metody?mockedList.size()
zwracaint
wartość domyślnąint
0 w Javie. Jeśli spróbujesz wykonaćassertEquals(0, mockedList.size());
późniejmockedList.clear();
, wynik pozostanie taki sam.Jeśli istnieje obiekt z 8 metodami i masz test, w którym chcesz wywołać 7 prawdziwych metod, a jedną z nich usunąć, masz dwie opcje:
spy
, musisz go ustawić, odrzucając jedną metodęOficjalna dokumentacja na
doCallRealMethod
zaleca stosowanie szpiegiem częściowych mocks.źródło
Szpieg może być przydatny, gdy chcesz tworzyć testy jednostkowe dla starszego kodu .
Utworzyłem tutaj działający przykład https://www.surasint.com/mockito-with-spy/ , część z niego kopiuję tutaj.
Jeśli masz coś takiego jak ten kod:
Możesz nie potrzebować szpiega, ponieważ możesz po prostu udawać usługę DepositMoneyService i WithdrawMoneyService.
Ale w przypadku niektórych starszych kodów zależność jest w kodzie w następujący sposób:
Tak, możesz przejść do pierwszego kodu, ale potem API jest zmieniane. Jeśli ta metoda jest używana w wielu miejscach, musisz zmienić je wszystkie.
Alternatywą jest to, że możesz wyodrębnić zależność w następujący sposób:
Następnie możesz użyć szpiega i wstrzyknąć zależność w następujący sposób:
Więcej szczegółów w powyższym linku.
źródło
Mock
jest nagim, podwójnym obiektem. Ten obiekt ma te same sygnatury metod, ale realizacja jest pusta i zwraca wartość domyślną - 0 i nullSpy
jest sklonowanym podwójnym obiektem. Nowy obiekt jest klonowany na podstawie prawdziwego obiektu, ale masz możliwość kpiny[Testuj podwójne typy]
źródło