Come posso usare l'iniezione con Mockito e JUnit 5?
In JUnit4 posso semplicemente usare @RunWith(MockitoJUnitRunner.class)
Annotation. In JUnit5 non c'è @RunWith
annotazione?
Come posso usare l'iniezione con Mockito e JUnit 5?
In JUnit4 posso semplicemente usare @RunWith(MockitoJUnitRunner.class)
Annotation. In JUnit5 non c'è @RunWith
annotazione?
Risposte:
Esistono diversi modi per utilizzare Mockito: li esaminerò uno per uno.
La creazione manuale di mock con Mockito::mock
funziona indipendentemente dalla versione di JUnit (o dal framework di test per quella materia).
L'utilizzo dell'annotazione @Mock e la chiamata corrispondente a MockitoAnnotations::initMocks
per creare mock funziona indipendentemente dalla versione di JUnit (o dal framework di test, ma Java 9 potrebbe interferire qui, a seconda che il codice di test finisca in un modulo o meno).
JUnit 5 ha un potente modello di estensione e Mockito ne ha recentemente pubblicato uno con l'ID gruppo / artefatto org.mockito : mockito-junit-jupiter .
Puoi applicare l'estensione aggiungendo @ExtendWith(MockitoExtension.class)
alla classe di test e annotando i campi derisi con @Mock
. Dal MockitoExtension
JavaDoc di:
@ExtendWith(MockitoExtension.class)
public class ExampleTest {
@Mock
private List list;
@Test
public void shouldDoSomething() {
list.add(100);
}
}
La documentazione di MockitoExtension descrive altri modi per istanziare i mock, ad esempio con l'iniezione nel costruttore (se si rpefer i campi finali nelle classi di test).
Le regole ei corridori di JUnit 4 non funzionano in JUnit 5, quindi non è possibile utilizzare MockitoRule
il corridore e il Mockito .
@Test
deve essere pubblico o "pacchetto privato" è abbastanza buono?
Usa Mockito's MockitoExtension
. L'estensione è contenuta in un nuovo artefatto mockito-junit-jupiter
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
Ti consente di scrivere test come faresti con JUnit 4:
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)
è l'equivalente di @RunWith(MockitoJUnitRunner.class)
JUnit4
Ci sono diversi modi per farlo, ma il modo più pulito e che rispetta anche la filosofia di JUnit 5 è creare un org.junit.jupiter.api.extension.Extension
per Mockito.
1) La creazione manuale di mock fa perdere il vantaggio di ulteriori controlli Mockito per assicurarsi di utilizzare correttamente il framework.
2) La chiamata MockitoAnnotations.initMocks(this)
in ogni classe di prova è un codice di targa che potremmo evitare.
E anche fare questa configurazione in una classe astratta non è una buona soluzione.
Associa ogni classe di test a una classe base.
Se poi hai bisogno di una nuova classe di test di base per buoni motivi, finisci con una gerarchia di classi a 3 livelli. Si prega di evitarlo.
3) Test Rules è una specificità di JUnit 4.
Non pensarci nemmeno.
E la documentazione è chiara su questo:
Tuttavia, se intendi sviluppare una nuova estensione per JUnit 5, utilizza il nuovo modello di estensione di JUnit Jupiter invece del modello basato su regole di JUnit 4.
4) Test Runner non è davvero il modo per estendere il framework JUnit 5.
JUnit 5 ha semplificato l'inferno dei Runners di JUnit 4 fornendo un modello di estensione per la scrittura di test grazie a JUnit 5 Extensions.
Non pensarci nemmeno.
Quindi favorisci la org.junit.jupiter.api.extension.Extension
via.
EDIT: In realtà, Mockito racchiude un'estensione di Giove: mockito-junit-jupiter
Quindi, molto semplice da usare:
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class FooTest {
...
}
Ecco un'aggiunta all'eccellente risposta di Jonathan.
Aggiungendo come dipendenza l' mockito-junit-jupiter
artefatto, l'uso di ha @ExtendWith(MockitoExtension.class)
prodotto la seguente eccezione durante l'esecuzione del test:
java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Optional; Ljava / lang / Class;) Ljava / util / Optional;
Il problema è che mockito-junit-jupiter
dipende da due librerie indipendenti. Ad esempio per 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>
Il problema è stato che ho usato junit-jupiter-api:5.0.1
.
Quindi, poiché si junit-jupiter-api
muove ancora spesso in termini di API, assicurati di dipendere dalla stessa versione da junit-jupiter-api
cui mockito-junit-jupiter
dipende.
mockito-junit-jupiter
estrae la versione corretta di junit-jupiter-api
?
mockito-junit-jupiter:2.19.0
. Mentre le versioni di JUnit Jupiter iniziano con 5
. mockito-junit-jupiter avrebbe dovuto specificare nel suo identificatore di artefatto le due cose (versione Mockito e versione JUnit Jupiter) per rendere le cose più chiare. Ad esempio mockito-junit-jupiter-5.1:2.19.0
per comunicare che la libreria è progettata per JUnit Jupiter 5.1.
MockitoExtension
non sembra esistere nella mockito-core
versione 3.0.0.
mockito-junit-jupiter
Devi usare la nuova @ExtendWith
annotazione.
Purtroppo non ci sono ancora estensioni ancora rilasciate. Su GitHub puoi vedere un'implementazione beta per l'estensione. come prova demo di esempio .