Vergleich zwischen Mockito und JMockit - warum wird Mockito besser gewählt als JMockit? [geschlossen]


124

Ich untersuche, welches Spott-Framework für mein Projekt verwendet werden soll, und habe es auf JMockit und Mockito eingegrenzt .

Ich stelle fest, dass Mockito auf Stackoverflow zum " besten Mock-Framework für Java " gewählt wurde.
Beim Vergleichen von Funktionen in JMockits " Mocking Tool Comparision Matrix " scheint es, dass JMockit mehrere verschiedene Funktionen hat.

Hat jemand spezifische Informationen (keine Meinungen) darüber, was Mockito tun kann, was mit JMockit nicht erreicht werden kann und umgekehrt?


2
vielleicht bessere Benutzerfreundlichkeit für Mockito, übrigens glaube ich nicht, dass JMockit reifer ist als Mockito ...
Alois Cochard

42
Gemessen an der Anzahl der Stimmen sind die Antworten auf diese Frage von der Community offensichtlich sehr gefragt. Dies bedeutet, dass die Orthogonalisierungsstrategie dieser Site, die dazu geführt hat, dass diese Frage geschlossen wurde, ernsthaft überarbeitet werden muss - da diese Site häufig auf den Fuß getreten ist, um die erforderlichen Antworten zu liefern, indem sie auf ihre falsch ausgerichtete Orthogonalität zurückgreift. Ohne zu erkennen, dass es bei der Diagrammanalyse eines Baums so viele Möglichkeiten gibt, die Orthogonalität eines Baums anzuzeigen, wie es Knoten gibt. Vielleicht ist die Orthogonalität dieser Site und nicht die der Frage falsch ausgerichtet.
Seliger Geek

9
+1 für nicht schließen. Diese Antworten haben eine Menge Wert. Die Auswahl einer Technologie ist nicht einfach und diese Fragen können viel Zeit sparen. In der Tat gibt es möglicherweise keine richtige Antwort, aber StackOverflow sollte Fragen ohne Antwort berücksichtigen.
mhstnsc

6
Ich werde meine Unterstützung denjenigen hinzufügen, die sagen, dass es lächerlich ist, dies als "nicht konstruktiv" zu schließen. Die hier gegebenen Antworten wurden durch "Fakten, Referenzen und / oder Fachwissen" gestützt. Eine Frage im Technologiebereich, die keine "Debatten, Umfragen oder ausführlichen Diskussionen" hervorruft, ist normalerweise kaum eine Frage wert. Darüber hinaus hängt die Bereitstellung von Fakten und Fachwissen von unterschiedlichen Erfahrungen ab - und diese Unterschiede werden zu Debatten und ausführlichen Diskussionen führen.
Jeff Nyman

@Alois - können Sie konkrete Beispiele nennen, bei denen JMockit weniger ausgereift aussieht als Mockito?
NitinS

Antworten:


140

Update Sep 2019: Das einzige von Spring Boot (standardmäßig) unterstützte Mockito- Framework ist Mockito . Wenn Sie Spring verwenden, liegt die Antwort auf der Hand.


Ich würde sagen, die Konkurrenz besteht zwischen JMockit und PowerMock , dann zwischen Mockito .

Ich würde "einfaches" jMock und EasyMock belassen, da sie nur Proxy und CGLIB verwenden und keine Java 5-Instrumentierung wie die neueren Frameworks verwenden.

jMock hatte auch über 4 Jahre lang keine stabile Version. jMock 2.6.0 benötigte 2 Jahre, um von RC1 zu RC2 zu wechseln, und dann weitere 2 Jahre, bevor es tatsächlich veröffentlicht wurde.

In Bezug auf Proxy & CGLIB vs. Instrumentierung:

(EasyMock und jMock) basieren auf java.lang.reflect.Proxy, für das eine Schnittstelle implementiert werden muss. Darüber hinaus unterstützen sie die Erstellung von Scheinobjekten für Klassen durch Generierung von CGLIB-Unterklassen. Aus diesem Grund können diese Klassen nicht endgültig sein und nur überschreibbare Instanzmethoden können verspottet werden. Am wichtigsten ist jedoch, dass bei Verwendung dieser Tools die Abhängigkeiten des zu testenden Codes (dh die Objekte anderer Klassen, von denen eine bestimmte zu testende Klasse abhängt) von den Tests gesteuert werden müssen, damit Scheininstanzen an die Clients übergeben werden können dieser Abhängigkeiten. Daher können Abhängigkeiten nicht einfach mit dem neuen Operator in einer Clientklasse instanziiert werden, für die Unit-Tests geschrieben werden sollen.

Letztendlich führen die technischen Einschränkungen herkömmlicher Verspottungswerkzeuge zu folgenden Konstruktionsbeschränkungen für den Produktionscode:

  1. Jede Klasse, die in einem Test verspottet werden muss, muss entweder eine separate Schnittstelle implementieren oder nicht endgültig sein.
  2. Die Abhängigkeiten jeder zu testenden Klasse müssen entweder über konfigurierbare Instanzerstellungsmethoden (Fabriken oder einen Service Locator) ermittelt oder für die Abhängigkeitsinjektion verfügbar gemacht werden. Andernfalls können Komponententests keine Scheinimplementierungen von Abhängigkeiten an die zu testende Einheit übergeben.
  3. Da nur Instanzmethoden verspottet werden können, können zu testende Klassen keine statischen Methoden für ihre Abhängigkeiten aufrufen oder sie mit einem der Konstruktoren instanziieren.

Das Obige wird von http://jmockit.org/about.html kopiert . Darüber hinaus vergleicht es sich (JMockit), PowerMock und Mockito auf verschiedene Weise:

Es gibt jetzt andere Verspottungstools für Java, die ebenfalls die Einschränkungen der herkömmlichen Tools überwinden, darunter PowerMock, jEasyTest und MockInject. Diejenige, die dem Funktionsumfang von JMockit am nächsten kommt, ist PowerMock, daher werde ich sie hier kurz bewerten (außerdem sind die beiden anderen eingeschränkter und scheinen nicht mehr aktiv entwickelt zu sein).

JMockit gegen PowerMock

  • Erstens bietet PowerMock keine vollständige API zum Verspotten, sondern fungiert als Erweiterung eines anderen Tools, das derzeit EasyMock oder Mockito sein kann. Dies ist offensichtlich ein Vorteil für bestehende Benutzer dieser Tools.
  • JMockit hingegen bietet völlig neue APIs, obwohl die Haupt-API (Expectations) sowohl EasyMock als auch jMock ähnelt. Dies führt zwar zu einer längeren Lernkurve, ermöglicht es JMockit jedoch auch, eine einfachere, konsistentere und benutzerfreundlichere API bereitzustellen.
  • Im Vergleich zur JMockit Expectations-API ist die PowerMock-API eher "low-level", sodass Benutzer herausfinden und angeben müssen, welche Klassen für das Testen vorbereitet werden müssen (mit der Annotation @PrepareForTest ({ClassA.class, ...}) ) und erfordern spezifische API-Aufrufe, um mit verschiedenen Arten von Sprachkonstrukten umzugehen, die im Produktionscode vorhanden sein können: statische Methoden (mockStatic (ClassA.class)), Konstruktoren (unterdrücken (Konstruktor (ClassXyz.class))), Konstruktoraufrufe ( requireNew (AClass.class)), partielle Mocks (createPartialMock (ClassX.class, "methodToMock")) usw.
  • Mit JMockit Expectations werden alle Arten von Methoden und Konstruktoren auf rein deklarative Weise verspottet, wobei Teilverspottungen durch reguläre Ausdrücke in der Annotation @Mocked oder durch einfaches "Entspotten" der Mitglieder ohne aufgezeichnete Erwartungen angegeben werden. Das heißt, der Entwickler deklariert einfach einige gemeinsam genutzte "Scheinfelder" für die Testklasse oder einige "lokale Scheinfelder" und / oder "Scheinparameter" für einzelne Testmethoden (und in diesem letzten Fall wird die Annotation @Mocked dies häufig nicht tun benötigt werden).
  • Einige in JMockit verfügbare Funktionen, z. B. die Unterstützung für das Verspotten von Equals und HashCode, überschriebene Methoden und andere, werden derzeit in PowerMock nicht unterstützt. Es gibt auch kein Äquivalent zu JMockits Fähigkeit, Instanzen und Scheinimplementierungen bestimmter Basistypen während der Testausführung zu erfassen, ohne dass der Testcode selbst Kenntnis von den tatsächlichen Implementierungsklassen hat.
  • PowerMock verwendet benutzerdefinierte Klassenlader (normalerweise einen pro Testklasse), um geänderte Versionen der verspotteten Klassen zu generieren. Eine derart häufige Verwendung von benutzerdefinierten Klassenladeprogrammen kann zu Konflikten mit Bibliotheken von Drittanbietern führen. Daher muss manchmal die Annotation @PowerMockIgnore ("package.to.be.ignored") für Testklassen verwendet werden.
  • Der von JMockit verwendete Mechanismus (Laufzeitinstrumentierung über einen "Java-Agenten") ist einfacher und sicherer, obwohl bei der Entwicklung unter JDK 1.5 ein Parameter "-javaagent" an die JVM übergeben werden muss. Unter JDK 1.6+ (das immer für die Entwicklung verwendet werden kann, auch wenn es auf einer älteren Version bereitgestellt wird) gibt es keine solche Anforderung, da JMockit den Java-Agenten bei Bedarf mithilfe der Attach-API transparent laden kann.

Ein weiteres aktuelles Verspottungswerkzeug ist Mockito. Obwohl nicht versucht wird, die Einschränkungen älterer Tools (jMock, EasyMock) zu überwinden, wird ein neuer Stil für Verhaltenstests mit Mocks eingeführt. JMockit unterstützt diesen alternativen Stil auch über die Verifications-API.

JMockit gegen Mockito

  • Mockito verlässt sich auf explizite Aufrufe seiner API, um den Code zwischen der Datensatzphase (wann (...)) und der Überprüfungsphase (verifizieren (...)) zu trennen. Dies bedeutet, dass für jeden Aufruf eines Scheinobjekts im Testcode auch die Verspottungs-API aufgerufen werden muss. Darüber hinaus führt dies häufig zu wiederholten (...) und verifizierten (Schein-) ... Aufrufen.
  • Mit JMockit existieren keine ähnlichen Aufrufe. Sicher, wir haben die neuen Konstruktoraufrufe NonStrictExpectations () und Verifications (), aber sie treten (normalerweise) nur einmal pro Test auf und sind völlig unabhängig von den Aufrufen verspotteter Methoden und Konstruktoren.
  • Die Mockito-API enthält mehrere Inkonsistenzen in der Syntax, die für Aufrufe verspotteter Methoden verwendet wird. In der Aufzeichnungsphase haben wir Aufrufe wie when (mock.mockedMethod (args)) ... während in der Überprüfungsphase derselbe Aufruf als verify (mock) .mockedMethod (args) geschrieben wird. Beachten Sie, dass im ersten Fall der Aufruf von mockedMethod direkt für das Mock-Objekt erfolgt, während er im zweiten Fall für das von verify (mock) zurückgegebene Objekt erfolgt.
  • JMockit weist keine derartigen Inkonsistenzen auf, da Aufrufe von verspotteten Methoden immer direkt auf den verspotteten Instanzen selbst erfolgen. (Mit nur einer Ausnahme: Um Aufrufe auf derselben verspotteten Instanz abzugleichen, wird ein Aufruf von onInstance (mock) verwendet, was zu Code wie onInstance (mock) .mockedMethod (args) führt. Die meisten Tests müssen dies jedoch nicht verwenden. )
  • Genau wie andere Verspottungswerkzeuge, die auf Methodenverkettung / -umbruch beruhen, stößt Mockito auch beim Stubben von void-Methoden auf eine inkonsistente Syntax. Zum Beispiel schreiben Sie when (mockedList.get (1)). ThenThrow (new RuntimeException ()); für eine nicht leere Methode und doThrow (neue RuntimeException ()). when (mockedList) .clear (); für eine Leere. Bei JMockit ist die Syntax immer dieselbe: mockedList.clear (); Ergebnis = neue RuntimeException ();.
  • Eine weitere Inkonsistenz tritt bei der Verwendung von Mockito-Spionen auf: "Mocks", mit denen die realen Methoden auf der Spionage-Instanz ausgeführt werden können. Wenn sich Spion beispielsweise auf eine leere Liste bezieht, müssen Sie anstelle von when (spy.get (0)). ThenReturn ("foo") doReturn ("foo"). When (spy) .get (schreiben) 0). Mit JMockit bietet die dynamische Verspottungsfunktion ähnliche Funktionen wie Spione, jedoch ohne dieses Problem, da echte Methoden nur während der Wiedergabephase ausgeführt werden.
  • In EasyMock und jMock, den ersten Verspottungs-APIs für Java, lag der Schwerpunkt ausschließlich auf der Aufzeichnung erwarteter Aufrufe verspotteter Methoden für Scheinobjekte, die (standardmäßig) keine unerwarteten Aufrufe zulassen. Diese APIs bieten auch die Aufzeichnung zulässiger Aufrufe für Scheinobjekte, die unerwartete Aufrufe zulassen. Dies wurde jedoch als Feature zweiter Klasse behandelt. Darüber hinaus gibt es mit diesen Tools keine Möglichkeit, Aufrufe von Mocks explizit zu überprüfen, nachdem der zu testende Code ausgeführt wurde. Alle diese Überprüfungen werden implizit und automatisch durchgeführt.
  • In Mockito (und auch in Unitils Mock) wird der entgegengesetzte Standpunkt vertreten. Alle Aufrufe zum Verspotten von Objekten, die während des Tests auftreten können, ob aufgezeichnet oder nicht, sind zulässig und werden niemals erwartet. Die Überprüfung wird explizit durchgeführt, nachdem der zu testende Code ausgeführt wurde, niemals automatisch.
  • Beide Ansätze sind zu extrem und daher nicht optimal. JMockit Expectations & Verifications ist die einzige API, mit der der Entwickler für jeden Test nahtlos die beste Kombination aus strengen (standardmäßig erwarteten) und nicht strengen (standardmäßig zulässigen) Scheinaufrufen auswählen kann.
  • Um klarer zu sein, weist die Mockito-API das folgende Manko auf. Wenn Sie überprüfen müssen, ob während des Tests ein Aufruf einer nicht ungültigen verspotteten Methode stattgefunden hat, der Test jedoch einen Rückgabewert von dieser Methode erfordert, der sich vom Standardwert für den Rückgabetyp unterscheidet, enthält der Mockito-Test doppelten Code: ein Aufruf von when (mock.someMethod ()). thenReturn (xyz) in der Aufzeichnungsphase und eine Überprüfung (mock) .someMethod () in der Überprüfungsphase. Mit JMockit kann immer eine strenge Erwartung aufgezeichnet werden, die nicht explizit überprüft werden muss. Alternativ kann für jede aufgezeichnete nicht strenge Erwartung eine Einschränkung für die Anzahl der Aufrufe (Zeiten = 1) angegeben werden (mit Mockito können solche Einschränkungen nur in einem Überprüfungsaufruf (Schein, Einschränkung) angegeben werden).
  • Mockito hat eine schlechte Syntax für Überprüfungen in der richtigen Reihenfolge und für vollständige Überprüfungen (dh es wird überprüft, ob alle Aufrufe von Scheinobjekten explizit überprüft wurden). Im ersten Fall muss ein zusätzliches Objekt erstellt und Aufrufe zur Überprüfung ausgeführt werden: InOrder inOrder = inOrder (mock1, mock2, ...). Im zweiten Fall müssen Aufrufe wie verifyNoMoreInteractions (mock) oder verifyZeroInteractions (mock1, mock2) getätigt werden.
  • Mit JMockit schreiben Sie einfach neue VerificationsInOrder () oder neue FullVerifications () anstelle von neuen Verifications () (oder neuen FullVerificationsInOrder (), um beide Anforderungen zu kombinieren). Sie müssen nicht angeben, welche Scheinobjekte betroffen sind. Keine zusätzlichen spöttischen API-Aufrufe. Als Bonus können Sie durch Aufrufen von unbestifiedInvocations () in einem geordneten Verifizierungsblock auftragsbezogene Verifizierungen durchführen, die in Mockito einfach nicht möglich sind.

Schließlich hat das JMockit-Test-Toolkit einen größeren Umfang und ehrgeizigere Ziele als andere Verspottungs-Toolkits, um eine vollständige und hochentwickelte Entwicklertestlösung bereitzustellen. Eine gute API zum Verspotten reicht auch ohne künstliche Einschränkungen nicht aus, um Tests produktiv zu erstellen. Ein IDE-unabhängiges, benutzerfreundliches und gut integriertes Code Coverage-Tool ist ebenfalls unerlässlich, und genau das möchte JMockit Coverage bieten. Ein weiterer Teil des Entwicklertest-Toolset, der mit zunehmender Größe der Testsuite nützlicher wird, ist die Möglichkeit, Tests nach einer lokalisierten Änderung des Produktionscodes schrittweise erneut auszuführen. Dies ist auch im Coverage-Tool enthalten.

(Zugegeben, die Quelle mag voreingenommen sein, aber gut ...)

Ich würde sagen, geh mit JMockit . Es ist am einfachsten zu verwenden, flexibel und funktioniert in nahezu allen Fällen, auch in schwierigen Fällen und Szenarien, in denen Sie die zu testende Klasse nicht steuern können (oder aus Kompatibilitätsgründen usw. nicht brechen können).

Meine Erfahrungen mit JMockit waren sehr positiv.


1
Ich habe jmockit noch nie verwendet, möchte aber der Diskussion ein weiteres Argument hinzufügen: Sehen Sie sich einen Google-Trendvergleich aller diskutierten Frameworks an. Ab dem 06.06.2012 wird JMockit im Vergleich zu Mockito und EasyMock nicht einmal im Google-Trenddiagramm angezeigt. Die Anzahl der Benutzer ist auch bei der Auswahl eines Frameworks wichtig.
Maschinen

3
Das ist ziemlich seltsam. Mockito und JMockIt geben mir 409 'bzw. 83' Treffer bei Google. Sicherlich sollte JMockIt zumindest auftauchen.
Thoredge

5
Ihre Antwort ist sehr hilfreich. Ich hatte vor, einfach Mockito zu verwenden, aber jetzt werde ich zuerst JMockit testen. Es klingt zu gut, es nicht zu versuchen. @machinery: Ja, es ist wichtig, die Trends zu betrachten, aber wenn Sie sie als Hauptkriterium auswählen, werden Sie auf den Hauptstrom beschränkt und vor Innovationen geschützt.
Deamon

1
Ich weiß, dass dies ein alter Thread ist, aber nachdem ich diese Rezension gelesen hatte, dachte ich, ich würde es auch versuchen. Ich muss sagen, an der Oberfläche ist JMockit sehr vielversprechend. Bisher habe ich jedoch festgestellt, dass die Unterstützung der Community dafür sehr mangelhaft ist. Ich habe ein großes Problem mit meinem Verständnis der Mock-API und nachdem ich meine Probleme veröffentlicht habe, habe ich in den 2 Tagen keine Antwort erhalten.
Eric B.

1
Die Antwort ist 8 Jahre alt, so dass viele Dinge in der Antwort nicht mehr richtig sind. Ein Punkt ist, dass JMockit -javaagentseit 1.42 ein Flag benötigt, da Sie sich seit Java 9 nicht mehr selbst anhängen können und das Finden geeigneter Workarounds offensichtlich nicht im Umfang des Entwicklers lag. Ein weiterer Punkt ist, dass JMockit es nicht mehr erlaubt, private Methoden und Konstruktoren zu verspotten, während PowerMock afaik macht.
Vampir

24

Ich habe sowohl mit Mockito als auch mit JMockit gearbeitet und meine Erfahrung mit ihnen ist:

  • Mockito:

    • implizites Verspotten (-> bessere Benutzerfreundlichkeit, aber die Gefahr, dass nicht zulässige Methodenaufrufe auf Mocks nicht erkannt werden)
    • explizite Überprüfung
  • EasyMock:

    • Spott erklären
    • implizite Überprüfung
  • JMockit:

    • unterstützt beide
  • Außerdem andere Vorteile von JMockit:

    • Wenn Sie sich über statische Methoden / Konstruktoren usw. lustig machen (z. B. eine sehr alte Legacy-Codebasis ohne UT erweitern), haben Sie zwei Möglichkeiten: 1) Mockito / EasyMock mit Powermock-Erweiterung oder 2) Jmockit
    • integrierter Abdeckungsbericht

Ich persönlich bevorzuge JMockit, das meiner Meinung nach funktionsreicher und flexibler ist, aber eine etwas steilere Lernkurve erfordert. Es gibt normalerweise mehrere Möglichkeiten, um den gleichen Spott-Effekt zu erzielen, und erfordert mehr Sorgfalt beim Entwerfen der Mocks.


Es gibt stackoverflow.com/questions/8003278/… "verifyNoMoreInteractions" Ich nehme an, wenn Sie pseudo-explizite Verspottung mit mockito
rogerdpack

15

Ich benutze jMockit nur wegen seiner Reflektionsbibliotheken in Deencapsultation.class. Eigentlich mag ich Mockitos Stil, aber ich weigere mich, meinen Code zu ändern und meine API zu verwirren, nur damit ein begrenztes Test-Framework darauf zugreifen kann. Und ich bin ein Fan davon, meinen gesamten Code zu testen. Daher möchte ich ein Framework, das private Methoden nicht einfach testen kann, nicht verwenden.

Dieser Artikel hat mich beeinflusst

Nach einer (zugegebenermaßen großen) Lernkurve ist jMockit jetzt mein Haupt-Unit-Test-Framework für Mocks.


7
Wenn Sie der Meinung sind, dass Sie private Methoden testen müssen, sind Sie möglicherweise zu besorgt darüber, wie Ihr Code funktioniert, und nicht darüber, was er tut (was der eigentliche Punkt ist und was durch Ausübung nur seiner öffentlichen Methoden bestimmt werden kann). Ich würde auch gerne diesen Artikel lesen, aber der Link ist defekt.
Codebox

Verwenden Sie 4 Jahre später immer noch jMockit als primäres Testframework? Ich probiere es zum ersten Mal aus und stoße auf einige Probleme, aber ich weiß nicht, ob ich falsch verstehe, wie jMockit funktioniert, oder ob es eine Funktion ist, die es einfach nicht gibt.
Eric B.

jMockit unterstützt das Testen privater Methoden nicht mehr. Die Entkapselungsklasse wurde langsam veraltet und dann in Version 1.47 vollständig entfernt. jmockit.github.io/changes.html
Pytry

4

Für das einfache Testen unserer Legacy-Codebasis (mit vielen statischen Methodenaufrufen usw.) war JMockit von unschätzbarem Wert. [Schamloser Plug für einen Artikel in meinem Blog]


0

Ich persönlich bevorzuge EasyMock .
Die Fähigkeit, zwischen netten, normalen und strengen Verspottungskontrollen umzuschalten, ist eine meiner Lieblingsfunktionen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.