Porównanie Mockito vs JMockit - dlaczego Mockito został wybrany lepiej niż JMockit? [Zamknięte]

124

Śledztwo, które szyderczy ramy używać dla mojego projektu i mają zawężony go JMockit i Mockito .

Zauważyłem, że Mockito został wybrany „ najlepszym makietowym frameworkiem dla Javy ” w Stackoverflow.
Porównując funkcje na JMockit „s« Mocking Narzędzie Porównanie Matrix »wydaje się, że JMockit ma wiele różnych funkcji.

Czy ktoś ma jakieś konkretne informacje (nie opinie) na temat tego, co potrafi Mockito , czego nie da się osiągnąć z JMockitem i odwrotnie?

Rogério
źródło
2
być może lepsza użyteczność dla mockito, przy okazji nie sądzę, że JMockit jest bardziej dojrzały niż Mockito ...
Alois Cochard
42
Sądząc po liczbie głosów, OCZYWIŚCIE odpowiedzi na to pytanie są bardzo poszukiwane przez społeczność. Co oznacza, że ​​strategia ortogonalizacji tej witryny, która spowodowała zamknięcie tego pytania, wymaga poważnego przemyślenia - strona ta często stawała na nogi, będąc w stanie udzielić potrzebnych odpowiedzi, popadając w swoją źle wyrównaną ortogonalność. Nie zdając sobie sprawy, że w analizie drzewa na wykresie jest tyle sposobów, aby zobaczyć ortogonalność drzewa, ile istnieje węzłów. Być może ortogonalność tej witryny, a nie pytanie, jest źle wyrównana.
Blessed Geek,
9
+1 za niezamykanie. Te odpowiedzi mają mnóstwo wartości. Wybór technologii nie jest łatwy, a te pytania mogą zaoszczędzić sporo czasu. Rzeczywiście, może nie być właściwej odpowiedzi, ale StackOverflow powinien pomieścić pytania bez odpowiedzi.
mhstnsc
6
Dodam swoje poparcie dla tych, którzy twierdzą, że zamknięcie tego jako „nie konstruktywne” jest śmieszne. Udzielone tutaj odpowiedzi zostały poparte „faktami, referencjami i / lub ekspertyzą”. Pytanie z dziedziny technologii, które nie skłania do „debat, sondaży lub rozszerzonej dyskusji”, jest zwykle ledwie warte zadawania. Co więcej, dostarczanie faktów i ekspertyzy opiera się na różnych doświadczeniach - a te różnice doprowadzą do debaty i rozszerzonej dyskusji.
Jeff Nyman
@Alois - czy możesz podać konkretne przykłady, w których JMockit wygląda mniej dojrzale niż Mockito?
NitinS,

Odpowiedzi:

140

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:

  1. Każda klasa, która może wymagać wyśmiewania w teście, musi albo implementować oddzielny interfejs, albo nie może być ostateczna.
  2. 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.
  3. 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.

Hendy Irawan
źródło
1
Nigdy nie korzystałem z jmockit, ale chciałbym dodać kolejny argument do dyskusji: spójrz na porównanie Google trendów wszystkich omawianych frameworków. Od 06.06.2012 JMockit nie pojawia się nawet na wykresie trendów Google w porównaniu z Mockito i EasyMock. Liczba użytkowników jest również ważna przy wyborze frameworka.
maszyny
3
To dość dziwne. Mockito i JMockIt dają mi odpowiednio 409 'i 83' hity w Google. Z pewnością JMock Powinien się przynajmniej pojawić.
thoredge
5
Twoja odpowiedź jest bardzo pomocna. Planowałem po prostu użyć Mockito, ale teraz najpierw przetestuję JMockit. Brzmi zbyt dobrze, aby tego nie spróbować. @machinery: Tak, ważne jest, aby spojrzeć na trendy, ale wybranie go jako głównego kryterium ograniczy cię do głównego nurtu i ochroni przed innowacjami.
demon
1
Wiem, że to stary wątek, ale po przeczytaniu tej recenzji pomyślałem, że też spróbuję. Muszę powiedzieć, że na pozór JMockit jest bardzo obiecujący. Jednak do tej pory bardzo brakuje mi wsparcia społeczności. Mam duży problem ze zrozumieniem Mock API i po opublikowaniu moich problemów nie otrzymałem odpowiedzi w ciągu 2 dni.
Eric B.
1
Odpowiedź ma 8 lat, więc wiele rzeczy w odpowiedzi nie jest już poprawnych. Jedną kwestią jest to, że JMockit wymaga -javaagentflagi od wersji 1.42, ponieważ nie można już dołączyć samodzielnie, ponieważ Java 9 i znajdowanie odpowiednich obejść oczywiście nie było w zakresie programisty. Inną kwestią jest to, że JMockit nie pozwala już na mockowanie prywatnych metod i konstruktorów, podczas gdy PowerMock robi to afaik.
Vampire
24

Pracowałem zarówno z Mockito, jak i JMockit, a moje doświadczenie z nimi to:

  • Mockito:

    • niejawne mockowanie (-> lepsza użyteczność, ale grozi niepowodzeniem wykrycia niedozwolonych wywołań metod na próbach)
    • jawna weryfikacja
  • EasyMock:

    • jawne kpiny
    • niejawna weryfikacja
  • JMockit:

    • obsługuje oba
  • Poza tym inne zalety JMockit:

    • jeśli kpisz ze statycznych metod / konstruktorów itp. (np. rozszerzając bardzo stary kod źródłowy bez UT), masz dwie możliwości: 1) Mockito / EasyMock z rozszerzeniem Powermock lub 2) Jmockit
    • wbudowany raport pokrycia

Osobiście wolę JMockit, który moim zdaniem jest bardziej bogaty w funkcje i elastyczny, ale wymaga nieco bardziej stromej krzywej uczenia się. Zwykle istnieje wiele sposobów na osiągnięcie tego samego efektu kpiny i wymaga większej ostrożności podczas projektowania makiet.

Tumer
źródło
jest stackoverflow.com/questions/8003278/ ... "verifyNoMoreInteractions" Przypuszczam, że jeśli chcesz pseudo-jawne kpiny z mockito
rogerdpack
15

Używam jMockita tylko ze względu na jego biblioteki odbić w Deencapsultation.class. Właściwie uwielbiam styl Mockito, ale odmawiam zmiany kodu i zamulenia interfejsu API, aby uzyskać dostęp do ograniczonego środowiska testowego. Jestem fanem testowania całego mojego kodu, więc framework, który nie może łatwo przetestować prywatnych metod, nie jest tym, czego chcę.

Poruszył mnie ten artykuł

Po (wprawdzie dużej) krzywej uczenia się, jMockit jest teraz moim głównym frameworkiem do testowania jednostek dla prób.

Joseph Erickson
źródło
7
Być może, jeśli czujesz, że musisz przetestować metody prywatne, zbytnio przejmujesz się tym, jak działa Twój kod, a nie tym, co robi (co jest prawdziwym celem i co można określić, stosując tylko jego metody publiczne). Chciałbym również przeczytać ten artykuł, ale link jest uszkodzony.
codebox
Czy 4 lata później nadal używasz jMockit jako podstawowego środowiska testowego? Wypróbowuję go po raz pierwszy i napotykam na kilka problemów, ale nie wiem, czy to ja nie rozumiem, jak działa jMockit, czy jest to funkcja, która po prostu nie istnieje.
Eric B.
jMockit nie obsługuje już testowania metod prywatnych. Klasa Deencapsulation została powoli wycofana, a następnie całkowicie usunięta w wersji 1.47. jmockit.github.io/changes.html
Pytry
4

JMockit okazał się nieoceniony dla łatwego testowania naszej starszej bazy kodu (z wieloma wywołaniami metod statycznych itp.). [Bezwstydna wtyczka do artykułu na moim blogu]

Jeff Olson
źródło
0

Osobiście wolę EasyMock .
Moją ulubioną funkcją jest możliwość przełączania się między przyjemnymi, normalnymi i surowymi kontrolkami kpiny.

Bivas
źródło