Wie kann ich Mockito und JUnit 5 injizieren?
In JUnit4 kann ich nur die @RunWith(MockitoJUnitRunner.class)
Annotation verwenden. In JUnit5 ist keine @RunWith
Anmerkung?
Wie kann ich Mockito und JUnit 5 injizieren?
In JUnit4 kann ich nur die @RunWith(MockitoJUnitRunner.class)
Annotation verwenden. In JUnit5 ist keine @RunWith
Anmerkung?
Antworten:
Es gibt verschiedene Möglichkeiten, Mockito zu verwenden - ich werde sie einzeln durchgehen.
Das manuelle Erstellen von Mocks mit Mockito::mock
funktioniert unabhängig von der JUnit-Version (oder dem Testframework).
Mit Hilfe der @Mock -annotation und den entsprechenden Aufruf MockitoAnnotations::initMocks
zu Mocks erstellen funktioniert unabhängig von der JUnit - Version (oder Test - Framework für diese Angelegenheit , aber Java 9 könnte hier stören, je nachdem , ob der Testcode endet in einem Modul oder nicht).
JUnit 5 verfügt über ein leistungsstarkes Erweiterungsmodell, und Mockito hat kürzlich eines unter der Gruppen- / Artefakt-ID org.mockito veröffentlicht : mockito-junit-jupiter .
Sie können die Erweiterung anwenden, indem Sie sie @ExtendWith(MockitoExtension.class)
zur Testklasse hinzufügen und verspottete Felder mit Anmerkungen versehen @Mock
. Aus MockitoExtension
JavaDoc:
@ExtendWith(MockitoExtension.class)
public class ExampleTest {
@Mock
private List list;
@Test
public void shouldDoSomething() {
list.add(100);
}
}
In der MockitoExtension-Dokumentation werden andere Möglichkeiten zum Instanziieren von Mocks beschrieben, z. B. mit Konstruktorinjektion (wenn Sie die letzten Felder in Testklassen angeben).
JUnit 4-Regeln und -Läufer funktionieren in JUnit 5 nicht, daher können der MockitoRule
und der Mockito-Läufer nicht verwendet werden.
@Test
öffentlich sein oder ist "package private" gut genug?
Verwenden Sie Mockitos MockitoExtension
. Die Erweiterung ist in einem neuen Artefakt enthalten mockito-junit-jupiter
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
Sie können damit Tests schreiben, wie Sie es mit JUnit 4 getan hätten:
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@ExtendWith(MockitoExtension.class)
class MyTest {
@Mock
private Foo foo;
@InjectMocks
private Bar bar; // constructor injection
...
}
@ExtendWith(MockitoExtension.class)
entspricht @RunWith(MockitoJUnitRunner.class)
dem JUnit4
Es gibt verschiedene Möglichkeiten, aber die sauberere Art und Weise, und das respektiert auch die JUnit 5-Philosophie, schafft eine org.junit.jupiter.api.extension.Extension
für Mockito.
1) Wenn Sie Mocks manuell erstellen, verlieren Sie den Vorteil zusätzlicher Mockito-Prüfungen, um sicherzustellen, dass Sie das Framework korrekt verwenden.
2) Das Aufrufen MockitoAnnotations.initMocks(this)
jeder Testklasse ist ein Kesselplattencode, den wir vermeiden könnten.
Und dieses Setup in einer abstrakten Klasse zu machen, ist auch keine gute Lösung.
Es koppelt jede Testklasse mit einer Basisklasse.
Wenn Sie dann aus guten Gründen eine neue Basistestklasse benötigen, schließen Sie mit einer 3-stufigen Klassenhierarchie ab. Bitte vermeiden Sie das.
3) Testregeln sind eine JUnit 4-Spezifität.
Denk nicht mal daran.
Und die Dokumentation ist darüber klar:
Wenn Sie jedoch eine neue Erweiterung für JUnit 5 entwickeln möchten, verwenden Sie bitte das neue Erweiterungsmodell von JUnit Jupiter anstelle des regelbasierten Modells von JUnit 4.
4) Test Runner ist wirklich nicht die Möglichkeit, das JUnit 5-Framework zu erweitern.
JUnit 5 vereinfachte die Hölle der Läufer von JUnit 4, indem es dank JUnit 5-Erweiterungen ein Erweiterungsmodell zum Schreiben von Tests bereitstellte.
Denk nicht mal daran.
Also favorisiere den org.junit.jupiter.api.extension.Extension
Weg.
EDIT: Eigentlich bündelt Mockito eine Jupiter-Erweiterung: mockito-junit-jupiter
Dann sehr einfach zu bedienen:
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class FooTest {
...
}
Hier ist eine Ergänzung zu der hervorragenden Antwort von Jonathan.
Durch Hinzufügen des mockito-junit-jupiter
Artefakts als Abhängigkeit wurde bei der @ExtendWith(MockitoExtension.class)
Ausführung des Tests die folgende Ausnahme erzeugt:
java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Optional; Ljava / lang / Class;) Ljava / util / Optional;
Das Problem ist, dass es mockito-junit-jupiter
von zwei unabhängigen Bibliotheken abhängt. Zum Beispiel für mockito-junit-jupiter:2.19.0
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.19.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.1.0</version>
<scope>runtime</scope>
</dependency>
Das Problem war, dass ich benutzt habe junit-jupiter-api:5.0.1
.
Da junit-jupiter-api
sich die API immer noch häufig ändert, stellen Sie sicher, dass Sie von derselben Version abhängig sind, von junit-jupiter-api
der dies mockito-junit-jupiter
abhängt.
mockito-junit-jupiter
die richtige Version von junit-jupiter-api
?
mockito-junit-jupiter:2.19.0
. Während JUnit Jupiter-Versionen mit beginnen 5
. mockito-junit-jupiter sollte in seiner Artefaktkennung die beiden Dinge (Mockito-Version und JUnit Jupiter-Version) angegeben haben, um die Dinge klarer zu machen. Zum Beispiel mockito-junit-jupiter-5.1:2.19.0
, um zu vermitteln, dass die Bibliothek für JUnit Jupiter 5.1 ausgelegt ist.
MockitoExtension
scheint in mockito-core
Version 3.0.0 nicht zu existieren .
mockito-junit-jupiter
Sie müssen die neue @ExtendWith
Anmerkung verwenden.
Leider gibt es noch keine Erweiterung. Auf github sehen Sie eine Beta-Implementierung für die Erweiterung. als Beispiel Demo-Test .