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' @RunWithannotation?
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' @RunWithannotation?
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 MockitoExtensionle 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 MockitoRuleet le coureur de Mockito ne peuvent pas être utilisés.
@Testneeds 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.Extensionpour 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.Extensionchemin.
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-jupiterartefact, 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-jupiterdé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-apicelle dont mockito-junit-jupiterdépend.
mockito-junit-jupitertire 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.0pour indiquer que la bibliothèque est conçue pour JUnit Jupiter 5.1.
MockitoExtensionne semble pas exister dans la mockito-coreversion 3.0.0.
mockito-junit-jupiter
Vous devez utiliser la nouvelle @ExtendWithannotation.
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 .