Comment puis-je utiliser l'injection avec Mockito et JUnit 5?
Dans JUnit4, je peux simplement utiliser l' @RunWith(MockitoJUnitRunner.class)
annotation. Dans JUnit5, il n'y a pas d' @RunWith
annotation?
Comment puis-je utiliser l'injection avec Mockito et JUnit 5?
Dans JUnit4, je peux simplement utiliser l' @RunWith(MockitoJUnitRunner.class)
annotation. Dans JUnit5, il n'y a pas d' @RunWith
annotation?
Réponses:
Il existe différentes façons d'utiliser Mockito - je vais les parcourir une par une.
Créer des simulations manuellement avec Mockito::mock
fonctionne quelle que soit la version de JUnit (ou le framework de test d'ailleurs).
L'utilisation de l' annotation @Mock et de l'appel correspondant à MockitoAnnotations::initMocks
pour créer des simulations fonctionne quelle que soit la version de JUnit (ou le framework de test d'ailleurs, mais Java 9 pourrait interférer ici, selon que le code de test se termine dans un module ou non).
JUnit 5 a un modèle d'extension puissant et Mockito en a récemment publié un sous l'ID de groupe / artefact org.mockito : mockito-junit-jupiter .
Vous pouvez appliquer l'extension en ajoutant @ExtendWith(MockitoExtension.class)
à la classe de test et en annotant les champs simulés avec @Mock
. Depuis MockitoExtension
le JavaDoc de:
@ExtendWith(MockitoExtension.class)
public class ExampleTest {
@Mock
private List list;
@Test
public void shouldDoSomething() {
list.add(100);
}
}
La documentation MockitoExtension décrit d'autres façons d'instancier des simulations, par exemple avec l'injection de constructeur (si vous référez les champs finaux dans les classes de test).
Les règles et les coureurs de JUnit 4 ne fonctionnent pas dans JUnit 5, donc le MockitoRule
et le coureur de Mockito ne peuvent pas être utilisés.
@Test
needs doit-elle être publique ou "package private" est-il suffisant?
Utilisez Mockito MockitoExtension
. L'extension est contenue dans un nouvel artefact mockito-junit-jupiter
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
Il vous permet d'écrire des tests comme vous le feriez avec 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)
équivaut à de @RunWith(MockitoJUnitRunner.class)
la JUnit4
Il existe différentes façons de faire, mais la manière la plus propre et qui respecte également la philosophie de JUnit 5 est de créer un org.junit.jupiter.api.extension.Extension
pour Mockito.
1) La création manuelle de simulacres fait perdre l'avantage de vérifications supplémentaires Mockito pour vous assurer d'utiliser correctement le framework.
2) L'appel MockitoAnnotations.initMocks(this)
dans toutes les classes de test est un code de plaque chauffante que nous pourrions éviter.
Et faire cette configuration dans une classe abstraite n'est pas non plus une bonne solution.
Il couple toutes les classes de test à une classe de base.
Si vous avez besoin d'une nouvelle classe de test de base pour de bonnes raisons, vous terminez avec une hiérarchie de classes à 3 niveaux. Veuillez éviter cela.
3) Test Rules est une spécificité de JUnit 4.
N'y pense même pas.
Et la documentation est claire à ce sujet:
Cependant, si vous avez l'intention de développer une nouvelle extension pour JUnit 5, veuillez utiliser le nouveau modèle d'extension de JUnit Jupiter au lieu du modèle basé sur des règles de JUnit 4.
4) Test Runner n'est vraiment pas le moyen d'étendre le framework JUnit 5.
JUnit 5 a simplifié l'enfer des Runners de JUnit 4 en fournissant un modèle d'extension pour l'écriture de tests grâce aux extensions JUnit 5.
N'y pense même pas.
Alors privilégiez le org.junit.jupiter.api.extension.Extension
chemin.
EDIT: En fait, Mockito regroupe une extension Jupiter: mockito-junit-jupiter
Ensuite, très simple à utiliser:
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class FooTest {
...
}
Voici un ajout à l'excellente réponse de Jonathan.
En ajoutant comme dépendance l' mockito-junit-jupiter
artefact, l'utilisation de @ExtendWith(MockitoExtension.class)
produit l'exception suivante lors de l'exécution du test:
java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Optional; Ljava / lang / Class;) Ljava / util / Optional;
Le problème est que cela mockito-junit-jupiter
dépend de deux bibliothèques indépendantes. Par exemple pour 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>
Le problème était que j'utilisais junit-jupiter-api:5.0.1
.
Donc, comme cela junit-jupiter-api
évolue encore souvent en termes d'API, assurez-vous de dépendre de la même version de junit-jupiter-api
celle dont mockito-junit-jupiter
dépend.
mockito-junit-jupiter
tire pas la bonne version de junit-jupiter-api
?
mockito-junit-jupiter:2.19.0
. Alors que les versions de JUnit Jupiter commencent par 5
. mockito-junit-jupiter aurait dû spécifier dans son identifiant d'artefact les deux choses (version Mockito et version JUnit Jupiter) pour rendre les choses plus claires. Par exemple, mockito-junit-jupiter-5.1:2.19.0
pour indiquer que la bibliothèque est conçue pour JUnit Jupiter 5.1.
MockitoExtension
ne semble pas exister dans la mockito-core
version 3.0.0.
mockito-junit-jupiter
Vous devez utiliser la nouvelle @ExtendWith
annotation.
Malheureusement, il n'y a pas encore d'extension disponible. Sur github, vous pouvez voir une implémentation bêta de l'extension. comme exemple de test de démonstration .