Aktualizacja wrzesień 2019: Jedyną platformą do mockowania obsługiwaną (domyślnie) przez Spring Boot jest Mockito . Jeśli używasz Springa, odpowiedź jest dość oczywista.
Powiedziałbym, że jest konkurencja pomiędzy JMockit i PowerMock , potem Mockito .
Zostawiłbym „zwykły” jMock i EasyMock, ponieważ używają tylko proxy i CGLIB i nie używają instrumentacji Java 5 jak nowsze frameworki.
jMock również nie miał stabilnej wersji przez ponad 4 lata. jMock 2.6.0 potrzebował 2 lat, aby przejść z RC1 do RC2, a następnie kolejne 2 lata, zanim faktycznie został wydany.
Odnośnie proxy i CGLIB a instrumentacja:
(EasyMock i jMock) są oparte na java.lang.reflect.Proxy, co wymaga implementacji interfejsu. Dodatkowo obsługują tworzenie obiektów pozorowanych dla klas poprzez generowanie podklas CGLIB. Z tego powodu wspomniane klasy nie mogą być ostateczne i można mockować tylko metody instancji, które można zastąpić. Co jednak najważniejsze, przy korzystaniu z tych narzędzi zależności testowanego kodu (czyli obiektów innych klas, od których zależy dana testowana klasa) muszą być kontrolowane przez testy, tak aby można było przekazać klientom makiety tych zależności. Dlatego zależności nie można po prostu utworzyć instancji z operatorem new w klasie klienta, dla której chcemy napisać testy jednostkowe.
Ostatecznie ograniczenia techniczne konwencjonalnych narzędzi do makietowania nakładają następujące ograniczenia projektowe na kod produkcyjny:
- Każda klasa, która może wymagać wyśmiewania w teście, musi albo implementować oddzielny interfejs, albo nie może być ostateczna.
- Zależności każdej testowanej klasy należy uzyskać za pomocą konfigurowalnych metod tworzenia instancji (fabryk lub lokalizatora usług) lub udostępnić do iniekcji zależności. W przeciwnym razie testy jednostkowe nie będą mogły przekazać próbnych implementacji zależności do testowanej jednostki.
- Ponieważ można mockować tylko metody instancji, klasy, które mają być testowane jednostkowo, nie mogą wywoływać żadnych metod statycznych na podstawie ich zależności ani tworzyć ich instancji przy użyciu żadnego z konstruktorów.
Powyższe jest skopiowane z http://jmockit.org/about.html . Ponadto porównuje między sobą (JMockit), PowerMock i Mockito na kilka sposobów:
Istnieją teraz inne narzędzia do makietowania dla Javy, które również przezwyciężają ograniczenia tradycyjnych, między innymi PowerMock, jEasyTest i MockInject. Najbardziej zbliżony do zestawu funkcji JMockit jest PowerMock, więc pokrótce go tutaj opiszę (poza tym pozostałe dwa są bardziej ograniczone i nie wydają się być już aktywnie rozwijane).
JMockit vs PowerMock
- Przede wszystkim PowerMock nie zapewnia pełnego API do mockowania, ale działa jako rozszerzenie innego narzędzia, którym obecnie może być EasyMock lub Mockito. Jest to oczywiście zaleta dla obecnych użytkowników tych narzędzi.
- Z drugiej strony JMockit zapewnia zupełnie nowe API, chociaż jego główne API (Expectations) jest podobne do EasyMock i jMock. Chociaż tworzy to dłuższą krzywą uczenia się, pozwala również JMockit zapewnić prostsze, bardziej spójne i łatwiejsze w użyciu API.
- W porównaniu do JMockit Expectations API, PowerMock API jest bardziej „niskopoziomowe”, zmuszając użytkowników do wymyślenia i określenia, które klasy muszą być przygotowane do testowania (z adnotacją @PrepareForTest ({ClassA.class, ...}) ) i wymagające określonych wywołań API do obsługi różnych rodzajów konstrukcji językowych, które mogą występować w kodzie produkcyjnym: metody statyczne (mockStatic (ClassA.class)), konstruktory (suppress (konstruktor (ClassXyz.class))), wywołania konstruktora ( ExpectNew (AClass.class)), częściowe mocks (createPartialMock (ClassX.class, "methodToMock")) itp.
- W JMockit Expectations wszystkie rodzaje metod i konstruktorów są mockowane w sposób czysto deklaratywny, z częściowym mockowaniem określonym za pomocą wyrażeń regularnych w adnotacji @Mocked lub po prostu przez „odblokowanie” członków bez zarejestrowanych oczekiwań; to znaczy, programista po prostu deklaruje niektóre współdzielone „pozorowane pola” dla klasy testowej lub niektóre „lokalne makiety pól” i / lub „pozorowane parametry” dla poszczególnych metod testowych (w tym ostatnim przypadku adnotacja @Mocked często nie być potrzebne).
- Niektóre funkcje dostępne w JMockit, takie jak obsługa mockowania równości i hashCode, zastępowane metody i inne, nie są obecnie obsługiwane w programie PowerMock. Nie ma również odpowiednika zdolności JMockit do przechwytywania instancji i próbnych implementacji określonych typów podstawowych w trakcie wykonywania testu, bez znajomości rzeczywistych klas implementacji przez sam kod testu.
- PowerMock używa niestandardowych programów ładujących klasy (zwykle po jednym na klasę testową) w celu wygenerowania zmodyfikowanych wersji wyimaginowanych klas. Tak intensywne użycie niestandardowych programów ładujących może prowadzić do konfliktów z bibliotekami innych firm, stąd potrzeba czasami używania adnotacji @PowerMockIgnore ("package.to.be.ignored") na klasach testowych.
- Mechanizm używany przez JMockit (instrumentacja środowiska wykonawczego za pośrednictwem „agenta Java”) jest prostszy i bezpieczniejszy, chociaż wymaga przekazania parametru „-javaagent” do maszyny JVM podczas programowania na JDK 1.5; na JDK 1.6+ (który zawsze może być używany do programowania, nawet jeśli zostanie wdrożony na starszej wersji) nie ma takiego wymagania, ponieważ JMockit może w sposób przezroczysty ładować agenta Java na żądanie za pomocą Attach API.
Innym ostatnio używanym narzędziem do kpiny jest Mockito. Chociaż nie próbuje przezwyciężyć ograniczeń starszych narzędzi (jMock, EasyMock), wprowadza nowy styl testowania zachowania za pomocą mocków. JMockit obsługuje również ten alternatywny styl za pośrednictwem Verifications API.
JMockit vs Mockito
- Mockito opiera się na jawnych wywołaniach swojego API w celu oddzielenia kodu między fazami zapisu (kiedy (...)) i weryfikacji (weryfikacja (...)). Oznacza to, że każde wywołanie pozorowanego obiektu w kodzie testowym będzie również wymagało wywołania fałszywego interfejsu API. Dodatkowo często prowadzi to do powtarzających się (...) i weryfikujących (próbnych) ... połączeń.
- W przypadku JMockit nie istnieją podobne wywołania. Jasne, mamy nowe wywołania konstruktora NonStrictExpectations () i nowe Verifications (), ale występują one tylko raz na test (zazwyczaj) i są całkowicie oddzielone od wywołań do mockowanych metod i konstruktorów.
- Interfejs API Mockito zawiera kilka niespójności w składni używanej do wywołań metod mockowanych. W fazie nagrywania mamy wywołania takie jak when (mock.mockedMethod (args)) ... podczas gdy w fazie weryfikacji to samo wywołanie zostanie zapisane jako verify (mock) .mockedMethod (args). Zauważ, że w pierwszym przypadku wywołanie mockedMethod jest wykonywane bezpośrednio na obiekcie mock, podczas gdy w drugim przypadku jest wykonywane na obiekcie zwróconym przez verify (mock).
- JMockit nie ma takich niespójności, ponieważ wywołania metod mockowanych są zawsze wykonywane bezpośrednio na samych mockowanych instancjach. (Z jednym wyjątkiem: aby dopasować wywołania w tym samym mockowanym wystąpieniu, używane jest wywołanie onInstance (mock), w wyniku czego powstaje kod taki jak onInstance (mock) .mockedMethod (args); większość testów nie będzie jednak musiała tego używać. )
- Podobnie jak inne narzędzia do mockowania, które opierają się na łączeniu / zawijaniu metod, Mockito również napotyka niespójną składnię podczas usuwania metod void. Na przykład piszesz when (mockedList.get (1)). ThenThrow (new RuntimeException ()); dla metody non-void i doThrow (new RuntimeException ()). when (mockedList) .clear (); dla pustego. W przypadku JMockit składnia jest zawsze taka sama: mockedList.clear (); wynik = nowy RuntimeException () ;.
- Kolejna niespójność występuje w używaniu szpiegów Mockito: „fałszywe”, które pozwalają na wykonanie prawdziwych metod na szpiegowanej instancji. Na przykład, jeśli spy odnosi się do pustej listy, to zamiast pisać when (spy.get (0)). ThenReturn ("foo"), będziesz musiał napisać doReturn ("foo"). When (spy) .get ( 0). Dzięki JMockit funkcja dynamicznego mockowania zapewnia podobną funkcjonalność do szpiegów, ale bez tego problemu, ponieważ prawdziwe metody są wykonywane tylko podczas fazy odtwarzania.
- W EasyMock i jMock, pierwszych fałszywych interfejsach API dla języka Java, skupiono się całkowicie na rejestrowaniu oczekiwanych wywołań metod mockowanych, dla obiektów pozorowanych, które (domyślnie) nie pozwalają na nieoczekiwane wywołania. Te interfejsy API zapewniają również rejestrowanie dozwolonych wywołań obiektów pozorowanych, które pozwalają na nieoczekiwane wywołania, ale było to traktowane jako funkcja drugiej klasy. Ponadto w przypadku tych narzędzi nie ma możliwości jawnego zweryfikowania wywołań makiet po wykonaniu testowanego kodu. Wszystkie takie weryfikacje są przeprowadzane niejawnie i automatycznie.
- W Mockito (a także w Unitils Mock) przyjęto przeciwny punkt widzenia. Wszelkie wywołania kpiny z obiektów, które mogą się zdarzyć podczas testu, niezależnie od tego, czy zostały nagrane, czy nie, są dozwolone, nigdy nie oczekuje się. Weryfikacja jest wykonywana jawnie po wykonaniu testowanego kodu, nigdy automatycznie.
- Oba podejścia są zbyt ekstremalne, a zatem mniej niż optymalne. JMockit Expectations & Verifications to jedyny interfejs API, który pozwala programiście bezproblemowo wybrać najlepszą kombinację ścisłych (domyślnie oczekiwanych) i nieścisłych (domyślnie dozwolonych) makiet wywołań dla każdego testu.
- Aby być bardziej zrozumiałym, Mockito API ma następującą wadę. Jeśli chcesz sprawdzić, czy podczas testu doszło do wywołania metody mockowanej, która nie jest pusta, ale test wymaga wartości zwracanej z tej metody, która różni się od wartości domyślnej dla typu zwracanego, test Mockito będzie miał zduplikowany kod: a when (mock.someMethod ()). thenReturn (xyz) w fazie nagrywania i weryfikacja (mock) .someMethod () w fazie weryfikacji. Dzięki JMockit zawsze można zarejestrować ścisłe oczekiwania, które nie muszą być jawnie weryfikowane. Alternatywnie, ograniczenie liczby wywołań (times = 1) można określić dla dowolnego zarejestrowanego niesprecyzowanego oczekiwania (w przypadku Mockito takie ograniczenia można określić tylko w wywołaniu weryfikacyjnym (próbnym, ograniczającym)).
- Mockito ma słabą składnię dla weryfikacji w kolejności i dla pełnych weryfikacji (czyli sprawdzania, czy wszystkie wywołania obiektów pozorowanych są jawnie weryfikowane). W pierwszym przypadku należy utworzyć dodatkowy obiekt i wykonać na nim wywołania do weryfikacji: InOrder inOrder = inOrder (mock1, mock2, ...). W drugim przypadku należy wykonać wywołania, takie jak verifyNoMoreInteractions (mock) lub verifyZeroInteractions (mock1, mock2).
- Dzięki JMockit po prostu piszesz nowe VerificationsInOrder () lub nowe FullVerifications () zamiast nowych Verifications () (lub nowe FullVerificationsInOrder (), aby połączyć oba wymagania). Nie ma potrzeby określania, które pozorowane obiekty są zaangażowane. Żadnych dodatkowych fałszywych wywołań API. Jako bonus, wywołując unverifiedInvocations () w zamówionym bloku weryfikacyjnym, możesz wykonywać weryfikacje związane z zamówieniami, które są po prostu niemożliwe w Mockito.
Wreszcie, JMockit Testing Toolkit ma szerszy zakres i bardziej ambitne cele niż inne zestawy narzędzi do modelowania, aby zapewnić kompletne i wyrafinowane rozwiązanie do testowania programistów. Dobre API do mockowania, nawet bez sztucznych ograniczeń, nie wystarczy do produktywnego tworzenia testów. Niezbędne jest również niezależne od IDE, łatwe w użyciu i dobrze zintegrowane narzędzie Pokrycie kodu i właśnie to ma zapewnić JMockit Coverage. Kolejnym elementem zestawu narzędzi deweloperskich do testowania, który stanie się bardziej przydatny wraz ze wzrostem rozmiaru zestawu testów, jest możliwość przyrostowego ponownego uruchamiania testów po zlokalizowanej zmianie w kodzie produkcyjnym; jest to również zawarte w narzędziu Pokrycie.
(oczywiście, źródło może być stronnicze, ale cóż ...)
Powiedziałbym, że idź z JMockit . Jest najłatwiejszy w użyciu, elastyczny i działa w prawie wszystkich przypadkach, nawet trudnych i scenariuszach, w których nie możesz kontrolować klasy do przetestowania (lub nie możesz jej złamać z powodu kompatybilności itp.).
Moje doświadczenia z JMockit są bardzo pozytywne.