Differenza tra @Mock, @MockBean e Mockito.mock ()

Quando si creano test e dipendenze di derisione, qual è la differenza tra questi tre approcci?

  1. @MockBean:

    @MockBean MyService myservice; 
  2. @Mock:

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

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

Semplice libreria di Mockito

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

e

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

provengono dalla libreria Mockito e sono funzionalmente equivalenti.
Consentono di prendere in giro una class o un’interfaccia e di registrare e verificare i comportamenti su di essa.

Il modo di utilizzare l’annotazione è più breve, quindi preferibile e spesso preferito.


Si noti che per abilitare le annotazioni di Mockito durante le esecuzioni del test, è necessario chiamare il metodo statico MockitoAnnotations.initMocks(this) .
Per evitare effetti collaterali tra i test, si consiglia di farlo prima di ogni esecuzione del test:

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

Un altro modo per abilitare le annotazioni di Mockito è annotare la class di test con @RunWith specificando il MockitoJUnitRunner che esegue questa attività e anche altre cose utili:

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

Libreria Spring Boot che include la libreria Mockito

Questa è davvero una class Spring Boot :

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

La class è inclusa nella libreria di spring-boot-test .

Permette di aggiungere Mockito mock in Spring ApplicationContext .
Se un bean, compatibile con la class dichiarata esiste nel contesto, lo sostituisce con la simulazione.
Se non è il caso, aggiunge il mock nel contesto come bean.

Riferimento Javadoc:

Annotazione che può essere utilizzata per aggiungere mock a Spring ApplicationContext.

Se qualsiasi singolo bean esistente dello stesso tipo definito nel contesto verrà sostituito dal mock, se nessun bean esistente viene definito ne verrà aggiunto uno nuovo.


Quando usi Mockito classico / semplice e quando usi @MockBean da Spring Boot?

I test unitari sono progettati per testare un componente isolato da altri componenti e anche i test di unità richiedono: essere il più rapidi ansible in termini di tempo di esecuzione poiché questi test possono essere eseguiti ogni giorno decine di volte sulle macchine dello sviluppatore.

Di conseguenza, ecco una semplice guida:

Mentre scrivi un test che non richiede alcuna dipendenza dal contenitore Spring Boot, il classico / semplice Mockito è il modo di seguirlo: è veloce e favorisce l’isolamento del componente testato.
Se il tuo test deve fare affidamento sul contenitore Spring Boot e vuoi anche aggiungere o prendere in giro uno dei bean contenitore: @MockBean di Spring Boot è il modo.


Uso tipico di Spring Boot @MockBean

Mentre scriviamo una class di test annotata con @WebMvcTest (sezione test web).

La documentazione Spring Boot lo riassume molto bene:

Spesso @WebMvcTest sarà limitato a un singolo controller e utilizzato in combinazione con @MockBean per fornire implementazioni @MockBean per i collaboratori richiesti.

Ecco un esempio:

 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")); } } 

Alla fine è facile da spiegare. Se guardi le javadoc delle annotazioni, vedrai le differenze:

@Mock: ( org.mockito.Mock )

 Mark a field as a mock. - Allows shorthand mock creation. - Minimizes repetitive mock creation code. - Makes the test class more readable. - Makes the verification error easier to read because the field name is used to identify the mock. 

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

 Annotation that can be used to add mocks to a Spring ApplicationContext. Can be used as a class level annotation or on fields in either @Configuration classs, or test classs that are @RunWith the SpringRunner. Mocks can be registered by type or by bean name. Any existing single bean of the same type defined in the context will be replaced by the mock, if no existing bean is defined a new one will be added. When @MockBean is used on a field, as well as being registered in the application context, the mock will also be injected into the field. 

Mockito.mock ()

 Its just the representation of a @Mock.