web-dev-qa-db-fra.com

Différence entre @Mock, @MockBean et Mockito.mock ()

Lors de la création de tests et de dépendances moqueuses, quelle est la différence entre ces trois approches?

  1. @MockBean:

    @MockBean
    MyService myservice;
    
  2. @Moquer:

    @Mock
    MyService myservice;
    
  3. Mockito.mock ()

    MyService myservice = Mockito.mock(MyService.class);
    
90
Doug

Bibliothèque Plain Mockito

import org.mockito.Mock;
...
@Mock
MyService myservice;

et

import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);

proviennent de la bibliothèque Mockito et sont fonctionnellement équivalents.
Ils permettent de se moquer d’une classe ou d’une interface et d’enregistrer et de vérifier les comportements sur celle-ci.

L'utilisation de l'annotation est plus courte, donc préférable et souvent préférée.


Notez que pour activer les annotations Mockito lors des exécutions de test, la méthode MockitoAnnotations.initMocks(this) static doit être appelée.
Pour éviter les effets secondaires entre les tests, il est conseillé de le faire avant chaque exécution de test:

@Before 
public void initMocks() {
    MockitoAnnotations.initMocks(this);
}

Une autre façon d'activer les annotations Mockito consiste à annoter la classe de test avec @RunWith en spécifiant le MockitoJUnitRunner effectuant cette tâche ainsi que d'autres tâches utiles:

@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}

Librairie Spring Boot encapsulant la bibliothèque Mockito

C'est en effet un Spring Boot class :

import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;

La classe est incluse dans la bibliothèque spring-boot-test.

Il permet d’ajouter des moquettes Mockito dans un Spring ApplicationContext.
Si un bean compatible avec la classe déclarée existe dans le contexte, il le remplace par le modèle.
Si ce n'est pas le cas, il ajoute la maquette dans le contexte sous la forme d'un haricot.

Référence Javadoc:

Annotation pouvant être utilisée pour ajouter des exemples à un Spring ApplicationContext.

...

Si un seul haricot existant du même type défini dans le contexte sera remplacé par le faux, si aucun haricot existant n'est défini, un nouveau sera ajouté.


Lorsque vous utilisez Mockito classique/uni et lorsque vous utilisez @MockBean de Spring Boot?

Les tests unitaires sont conçus pour tester un composant indépendamment des autres composants. Les tests unitaires ont également une exigence: être aussi rapides que possible en termes de temps d'exécution, car ces tests peuvent être exécutés chaque jour une douzaine de fois sur les machines du développeur.

Par conséquent, voici une ligne directrice simple:

Lorsque vous écrivez un test qui ne nécessite aucune dépendance du conteneur Spring Boot, le classique/classique Mockito est le chemin à suivre: il est rapide et favorise l’isolation du composant testé.
Si votre test doit s’appuyer sur le conteneur Spring Boot et , vous souhaitez également ajouter ou simuler l’un des beans conteneur: @MockBean de Spring Boot est le chemin.


Utilisation typique de Spring Boot @MockBean

Au moment où nous écrivons une classe de test annotée avec @WebMvcTest (tranche de test Web).

La documentation de Spring Boot résume très bien ceci:

Souvent, @WebMvcTest sera limité à un seul contrôleur et utilisé en combinaison avec @MockBean pour fournir une implémentation fictive aux collaborateurs requis.

Voici un exemple :

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private FooService fooServiceMock;

    @Test
    public void testExample() throws Exception {
         Foo mockedFoo = new Foo("one", "two");

         Mockito.when(fooServiceMock.get(1))
                .thenReturn(mockedFoo);

         mvc.perform(get("foos/1")
            .accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andExpect(content().string("one two"));
    }

}
134
davidxxx

À la fin, c'est facile à expliquer. Si vous ne regardez que dans les javadocs des annotations, vous verrez les différentes:

@Mock: (org.mockito.Mock)

Marquer un champ comme une maquette.

  • Permet la création de maquette abrégée.
  • Réduit au minimum le code de création répétée.
  • Rend la classe de test plus lisible.
  • Facilite la lecture de l'erreur de vérification, car le nom du champ est utilisé pour identifier la maquette.

@MockBean: (org.springframework.boot.test.mock.mockito.MockBean)

Annotation pouvant être utilisée pour ajouter des exemples à un Spring ApplicationContext. Peut être utilisé comme annotation au niveau de la classe ou sur des champs de @Configuration classes ou de classes de test qui sont @RunWith le SpringRunner.

Les maquettes peuvent être enregistrées par type ou par nom de bean. Tout bean unique existant du même type défini dans le contexte sera remplacé par la maquette, si aucun bean existant n'est défini, un nouveau sera ajouté.

Lorsque @MockBean est utilisé sur un champ, tout en étant enregistré dans le contexte de l'application, le modèle sera également injecté dans le champ.

Mockito.mock ()

C'est juste la représentation d'un @Mock.

9
Patrick