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:
- Jede Klasse, die in einem Test verspottet werden muss, muss entweder eine separate Schnittstelle implementieren oder nicht endgültig sein.
- 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.
- 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.