Verwendung von Mockito mit JUnit5

100

Wie kann ich Mockito und JUnit 5 injizieren?

In JUnit4 kann ich nur die @RunWith(MockitoJUnitRunner.class)Annotation verwenden. In JUnit5 ist keine @RunWithAnmerkung?

Daniel Käfer
quelle

Antworten:

143

Es gibt verschiedene Möglichkeiten, Mockito zu verwenden - ich werde sie einzeln durchgehen.

Manuell

Das manuelle Erstellen von Mocks mit Mockito::mockfunktioniert unabhängig von der JUnit-Version (oder dem Testframework).

Annotation Based

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).

Mockito-Erweiterung

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 MockitoExtensionJavaDoc:

@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).

Keine Regeln, keine Läufer

JUnit 4-Regeln und -Läufer funktionieren in JUnit 5 nicht, daher können der MockitoRuleund der Mockito-Läufer nicht verwendet werden.

Nicolai
quelle
6
Es gibt jetzt eine offizielle Mockito Junit5-Erweiterung, die der MockitoJUnitRunner -> mockito-junit-jupiter
dan carter
Als die offizielle Erweiterung für Mockito veröffentlicht wurde, schrieb ich
Marcin Zajączkowski
Muss die mit annotierte Methode @Testöffentlich sein oder ist "package private" gut genug?
Geek
Wenn Sie Tests mit Jupiter ausführen (oft als "JUnit 5" bezeichnet), müssen die Testmethoden nur für das Paket sichtbar sein.
Nicolai
53

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

    ...
}
Jonathan
quelle
4
@ExtendWith(MockitoExtension.class)entspricht @RunWith(MockitoJUnitRunner.class)dem JUnit4
Sergey
8

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.Extensionfü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.ExtensionWeg.


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-jupiterArtefakts 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-jupitervon 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-apisich die API immer noch häufig ändert, stellen Sie sicher, dass Sie von derselben Version abhängig sind, von junit-jupiter-apider dies mockito-junit-jupiterabhängt.

davidxxx
quelle
warum zieht nicht mockito-junit-jupiterdie richtige Version von junit-jupiter-api?
Haelix
@haelix Da die für diese Abhängigkeit verwendete Versionsstrategie von der Mockito-Bibliothek abhängt. Schauen Sie sich die Version hier an 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.
Davidxxx
MockitoExtensionscheint in mockito-coreVersion 3.0.0 nicht zu existieren .
Thunderforge
1
@Thunderforge Dies ist definiert inmockito-junit-jupiter
davidxxx
3

Sie müssen die neue @ExtendWithAnmerkung verwenden.

Leider gibt es noch keine Erweiterung. Auf github sehen Sie eine Beta-Implementierung für die Erweiterung. als Beispiel Demo-Test .

Daniel Käfer
quelle