Comment utiliser Mockito avec JUnit5

103

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?

Daniel Käfer
la source

Réponses:

144

Il existe différentes façons d'utiliser Mockito - je vais les parcourir une par une.

Manuellement

Créer des simulations manuellement avec Mockito::mock fonctionne quelle que soit la version de JUnit (ou le framework de test d'ailleurs).

Basé sur les annotations

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

Extension Mockito

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

Pas de règles, pas de coureurs

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.

Nicolai
la source
6
Il existe maintenant une extension officielle Mockito Junit5 qui est l'équivalent du MockitoJUnitRunner -> mockito-junit-jupiter
dan carter
Lorsque l'extension officielle pour Mockito a été publiée, a écrit un article de blog avec plus de détails sur la façon de la configurer et de l'utiliser: solidsoft.wordpress.com/2018/03/27/…
Marcin Zajączkowski
La méthode annotée avec @Testneeds doit-elle être publique ou "package private" est-il suffisant?
Geek
Lors de l'exécution de tests avec Jupiter (souvent appelés «JUnit 5»), les méthodes de test doivent uniquement être visibles sur le package.
Nicolai
56

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

    ...
}
Jonathan
la source
5
@ExtendWith(MockitoExtension.class)équivaut à de @RunWith(MockitoJUnitRunner.class)la JUnit4
Sergey Nemchinov
9

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.

davidxxx
la source
pourquoi ne mockito-junit-jupitertire pas la bonne version de junit-jupiter-api?
haelix
@haelix Parce que la stratégie de version utilisée pour cette dépendance repose sur la bibliothèque Mockito. Regardez la version ici 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.
davidxxx
MockitoExtensionne semble pas exister dans la mockito-coreversion 3.0.0.
Thunderforge
1
@Thunderforge Ceci est défini dansmockito-junit-jupiter
davidxxx
3

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 .

Daniel Käfer
la source