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.
La manière d'utiliser 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
MockitoAnnotations.initMocks(this)
méthode statique 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
qui effectue cette tâche ainsi que d'autres choses utiles:
@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}
Bibliothèque Spring Boot enveloppant la bibliothèque Mockito
Il s'agit en effet d'une classe Spring Boot :
import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
La classe est incluse dans la spring-boot-test
bibliothèque.
Il permet d'ajouter des mocks Mockito dans un printemps ApplicationContext
.
Si un bean, compatible avec la classe déclarée existe dans le contexte, il le remplace par le mock.
Si ce n'est pas le cas, il ajoute le mock dans le contexte en tant que bean.
Référence Javadoc:
Annotation qui peut être utilisée pour ajouter des simulations à un Spring ApplicationContext.
...
Si un bean unique existant du même type défini dans le contexte sera remplacé par le mock, si aucun bean existant n'est défini, un nouveau sera ajouté.
Quand utiliser Mockito classique / ordinaire et quand utiliser à @MockBean
partir de Spring Boot?
Les tests unitaires sont conçus pour tester un composant indépendamment des autres composants et les tests unitaires ont également une exigence: être aussi rapide que possible en termes de temps d'exécution car ces tests peuvent être exécutés chaque jour des dizaines de fois sur les machines de développement.
Par conséquent, voici une directive simple:
Lorsque vous écrivez un test qui ne nécessite aucune dépendance du conteneur Spring Boot, le Mockito classique / simple est la voie à suivre: il est rapide et favorise l'isolement du composant testé.
Si votre test doit s'appuyer sur le conteneur Spring Boot et que vous souhaitez également ajouter ou simuler l'un des beans conteneur: à @MockBean
partir de Spring Boot, c'est le moyen.
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 cela:
Souvent @WebMvcTest
limité à un seul contrôleur et utilisé en combinaison avec @MockBean
pour fournir des implémentations simulées 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"));
}
}
@MockBean
remplacera le bean dans le contexte de l'application si un bean déclarant le même type est déjà défini dans votre configuration Spring. Et l'injection est effectuée dans la classe où vous déclarez.@MockBean.
Les mécanismes DI fonctionnent de cette manière: vous enregistrez un objet dans le contexte DI puis vous pouvez injecter l'objet référencé dans le contexte Spring dans une classe spécifique. Vous n'injectez pas d'objet dans le contexte DI.À la fin, c'est facile à expliquer. Si vous regardez simplement dans les javadocs des annotations, vous verrez les différents:
@Mock: (
org.mockito.Mock
)@MockBean: (
org.springframework.boot.test.mock.mockito.MockBean
)Mockito.mock ()
la source
@MockBean
et@Mock
celle-là injectera la simulation dans laSpring ApplicationContext
et l'autre ne le fera pas?