Mam ostatnią klasę, coś takiego:
public final class RainOnTrees{
public void startRain(){
// some code here
}
}
Korzystam z tej klasy w innej klasie, takiej jak ta:
public class Seasons{
RainOnTrees rain = new RainOnTrees();
public void findSeasonAndRain(){
rain.startRain();
}
}
i w mojej klasie testowej JUnit, Seasons.java
bo chcę z niej kpić RainOnTrees
. Jak mogę to zrobić za pomocą Mockito?
Odpowiedzi:
Wyśmiewanie klas / metod statycznych / końcowych jest możliwe tylko w Mockito v2.
dodaj to do pliku oceny:
Nie jest to możliwe w Mockito v1 z FAQ Mockito :
źródło
Mockito 2 obsługuje teraz końcowe klasy i metody!
Ale na razie jest to funkcja „inkubująca”. Aktywacja wymaga kilku kroków opisanych w części Co nowego w Mockito 2 :
źródło
org.mockito.plugins.MockMaker
plik we właściwym folderze.Nie możesz kpić z ostatniej klasy za pomocą Mockito, ponieważ nie możesz tego zrobić sam.
To, co robię, to stworzyć nie-końcową klasę, aby owinąć klasę końcową i użyć jako delegata. Przykładem tego jest
TwitterFactory
klasa, a to moja próbna klasa:Wadą jest to, że istnieje wiele kodów typu „Boiler Plate”; zaletą jest to, że możesz dodać niektóre metody, które mogą odnosić się do Twojej działalności związanej z aplikacjami (np. getInstance, która bierze użytkownika zamiast accessToken, w powyższym przypadku).
W twoim przypadku stworzyłbym nie-końcową
RainOnTrees
klasę, która delegowałaby się do klasy ostatecznej. Lub, jeśli możesz sprawić, że będzie niefinałowy, byłoby lepiej.źródło
@Delegate
do obsługi dużej części płyty kotłowej.dodaj to do pliku oceny:
jest to konfiguracja umożliwiająca mockito pracę z klasami końcowymi
źródło
org.mockito.exceptions.base.MockitoInitializationException: Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)
Użyj Powermock. Ten link pokazuje, jak to zrobić: https://github.com/jayway/powermock/wiki/MockFinal
źródło
Powermock
dla wyśmianie końcowych klas i metody statyczne, aby zwiększyć zasięg mojego, który został urzędowo sprawdzane naSonarqube
. Pokrycie wynosiło 0% od SonarQube, z jakiegokolwiek powodu nie rozpoznaje klas, które używają Powermock nigdzie w nim. Zajęło mi to trochę czasu wraz z zespołem, aby zdać sobie z tego sprawę z jakiegoś wątku online. To tylko jeden z powodów, dla których powinieneś być ostrożny z Powermock i prawdopodobnie go nie używaj.Tylko po to. Dodaj ten wiersz do pliku oceny:
Próbowałem różnych wersji mockito-core i mockito-all. Żadne z nich nie działa.
źródło
Myślę, że udało ci się,
final
ponieważ chcesz zapobiec rozszerzaniu innych klasRainOnTrees
. Jak sugeruje Effective Java (punkt 15), istnieje inny sposób na utrzymanie klasy blisko do rozszerzenia bez robienia tegofinal
:Usuń
final
słowo kluczowe;Zrób jego konstruktora
private
. Żadna klasa nie będzie w stanie go rozszerzyć, ponieważ nie będzie w stanie wywołaćsuper
konstruktora;Utwórz statyczną metodę fabryczną, aby utworzyć instancję klasy.
Korzystając z tej strategii, będziesz mógł korzystać z Mockito i utrzymywać klasę zamkniętą, aby móc ją rozszerzać za pomocą niewielkiego kodu.
źródło
Miałem ten sam problem. Ponieważ klasa, którą próbowałem kpić, była prostą klasą, po prostu stworzyłem jej instancję i zwróciłem ją.
źródło
Wypróbuj to:
To zadziałało dla mnie. „SomeMockableType.class” to klasa nadrzędna tego, co chcesz wyśmiewać lub szpiegować, a someInstanceThatIsNotMockableOrSpyable to klasa, którą chcesz wyśmiewać lub szpiegować.
Aby uzyskać więcej informacji, zobacz tutaj
źródło
Innym obejściem, które może mieć zastosowanie w niektórych przypadkach, jest utworzenie interfejsu, który jest implementowany przez tę ostatnią klasę, zmiana kodu w celu użycia interfejsu zamiast konkretnej klasy, a następnie wyśmiewanie interfejsu. Pozwala to oddzielić umowę (interfejs) od implementacji (klasa końcowa). Oczywiście, jeśli naprawdę chcesz powiązać się z klasą końcową, nie będzie to miało zastosowania.
źródło
Właściwie jest jeden sposób, którego używam do szpiegowania. Przydałoby się to tylko wtedy, gdy spełnione są dwa warunki wstępne:
Proszę przywołać punkt 16 z Effective Java . Możesz utworzyć opakowanie (nie ostateczne) i przekazać wszystkie wywołania do instancji klasy końcowej:
Teraz możesz nie tylko kpić z ostatniej klasy, ale także szpiegować ją:
źródło
W Mockito 3 i więcej mam ten sam problem i naprawiłem go z tego linku
Wyśmiewaj końcowe klasy i metody za pomocą Mockito w następujący sposób
źródło
Oszczędność czasu dla osób, które borykają się z tym samym problemem (Mockito + klasa ostateczna) na Androidzie + Kotlin. Podobnie jak w przypadku Kotlin klasy są domyślnie ostateczne. Znalazłem rozwiązanie w jednym z przykładów Google Android z komponentem Architecture. Rozwiązanie wybrane tutaj: https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample
Utwórz następujące adnotacje:
Zmodyfikuj plik oceny. Weź przykład z tego miejsca: https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/build.gradle
Teraz możesz dodać adnotację do dowolnej klasy, aby była otwarta do testowania:
źródło
Można to zrobić, jeśli używasz Mockito2, z nową funkcją inkubacji, która obsługuje wyśmiewanie końcowych klas i metod.
Najważniejsze kwestie do zapamiętania:
1. Utwórz prosty plik o nazwie „org.mockito.plugins.MockMaker” i umieść go w folderze o nazwie „rozszerzenia mockito”. Ten folder powinien zostać udostępniony w ścieżce klasy.
2. Treść pliku utworzonego powyżej powinna być pojedynczą linią, jak podano poniżej:
mock-maker-inline
Powyższe dwa kroki są wymagane w celu aktywacji mechanizmu rozszerzenia mockito i skorzystania z tej opcji opt-in.
Przykładowe klasy są następujące:
FinalClass.java
}
Foo.java
}
FooTest.java
}
Mam nadzieję, że to pomoże.
Pełny artykuł obecny tutaj drwiący z niemożliwego do wyśmiewania .
źródło
Tak, ten sam problem tutaj, nie możemy kpić z ostatniej klasy z Mockito. Aby być dokładnym, Mockito nie może kpić / szpiegować następujących elementów:
Ale korzystanie z klasy otoki wydaje mi się dużą ceną do zapłaty, więc zamiast tego kup PowerMockito.
źródło
Myślę, że zasadniczo musisz więcej myśleć. Zamiast tego ostatnia klasa używa jego interfejsu i fałszywego interfejsu.
Dla tego:
Dodaj
i kpię z interfejsu:
źródło
Proszę spojrzeć na JMockit . Ma obszerną dokumentację z wieloma przykładami. Oto przykładowe rozwiązanie problemu (dla uproszczenia dodałem konstruktora
Seasons
do wstrzykiwania fałszywejRainOnTrees
instancji):źródło
Rozwiązania dostarczone wspólnie przez RC i Luigi R. Viggiano są prawdopodobnie najlepszym pomysłem.
Chociaż Mockito z założenia nie może kpić z klas końcowych, podejście do delegowania jest możliwe . Ma to swoje zalety:
W przypadku testowym celowo przekazujesz połączenia do testowanego systemu. Dlatego z założenia twoja dekoracja nic nie robi.
Dlatego test może również wykazać, że użytkownik może jedynie udekorować interfejs API zamiast go rozszerzać.
Mówiąc bardziej subiektywnie: wolę ograniczać frameworki do minimum, dlatego JUnit i Mockito są zwykle dla mnie wystarczające. W rzeczywistości ograniczenie tego sposobu czasami zmusza mnie również do refaktoryzacji na dobre.
źródło
Jeśli próbujesz uruchomić test jednostkowy w folderze testowym , najlepsze rozwiązanie jest w porządku. Wystarczy go dodać, dodając rozszerzenie.
Ale jeśli chcesz uruchomić go z klasą związaną z Androidem , taką jak kontekst lub aktywność, która znajduje się w folderze androidtest , odpowiedź jest dla Ciebie.
źródło
Dodaj te zależności, aby pomyślnie uruchomić mockito:
testImplementation 'org.mockito: mockito-core: 2.24.5'
testImplementation "org.mockito: mockito-inline: 2.24.5"
źródło
Jak powiedzieli inni, nie będzie to działać po wyjęciu z pudełka z Mockito. Sugerowałbym użycie refleksji do ustawienia określonych pól na obiekcie używanym przez testowany kod. Jeśli często to robisz, możesz zawinąć tę funkcję w bibliotekę.
Nawiasem mówiąc, jeśli jesteś jedynym, który zalicza zajęcia do klasy, przestań to robić. Natknąłem się na to pytanie, ponieważ pracuję z interfejsem API, w którym wszystko oznaczono jako ostateczne, aby zapobiec mojej uzasadnionej potrzebie rozszerzenia (kpiny) i żałuję, że programista nie założył, że nigdy nie będę musiał rozszerzać klasy.
źródło
final
powinna być domyślna.Dla nas było tak dlatego, że wykluczyliśmy mockito-inline z testu koin. Jeden moduł stopniowy faktycznie tego potrzebował i z powodu nie powiódł się tylko w kompilacjach wersji (kompilacje debugowania w IDE działały) :-P
źródło
Aby dodać klasę końcową, dodaj poniżej, aby udawać i nazwij statyczną lub niestatyczną.
1- dodaj to na poziomie klasy @SuppressStatucInitializationFor (wartość = {nazwa klasy z pakietem))
2- PowerMockito.mockStatic (classname.class) wyśmieje klasę
3, a następnie użyje instrukcji when, aby zwrócić obiekt próbny podczas wywoływania metody tej klasy.
Cieszyć się
źródło
Nie próbowałem ostatecznego, ale dla prywatnego, używając odbicia usuń modyfikator działał! sprawdziłem dalej, to nie działa na ostateczne.
źródło