Risposte:
Libreria Plain 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 deridere una classe o un'interfaccia e di registrare e verificare comportamenti su di essa.
Il modo in cui si utilizza l'annotazione è più breve, quindi preferibile e spesso preferito.
Si noti che per abilitare le annotazioni Mockito durante le esecuzioni di test, MockitoAnnotations.initMocks(this)
è necessario chiamare il
metodo statico.
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 Mockito è l'annotazione della classe test @RunWith
specificando MockitoJUnitRunner
ciò che fa questo compito e anche altre cose utili:
@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}
Libreria Spring Boot che avvolge la libreria Mockito
Questa è davvero una classe Spring Boot :
import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
La classe è inclusa nella spring-boot-test
libreria.
Permette di aggiungere beffe Mockito in una primavera ApplicationContext
.
Se nel contesto esiste un bean compatibile con la classe dichiarata, lo sostituisce con il mock.
In caso contrario, aggiunge il mock nel contesto come bean.
Riferimento Javadoc:
Annotazione che può essere utilizzata per aggiungere simulazioni a Spring ApplicationContext.
...
Se un singolo bean esistente dello stesso tipo definito nel contesto verrà sostituito dal mock, se non viene definito alcun bean esistente, 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 in isolamento da altri componenti e anche i test unitari hanno un requisito: essere il più veloci possibile in termini di tempo di esecuzione poiché questi test possono essere eseguiti ogni giorno dozzina di volte sulle macchine sviluppatore.
Di conseguenza, ecco una semplice linea guida:
Mentre scrivi un test che non necessita di dipendenze dal contenitore Spring Boot, il classico / semplice Mockito è il modo da seguire: è veloce e favorisce l'isolamento del componente testato.
Se il test deve fare affidamento sul contenitore Spring Boot e si desidera anche aggiungere o deridere uno dei bean container: @MockBean
da Spring Boot è la soluzione.
Utilizzo tipico di Spring Boot @MockBean
Mentre scriviamo una classe di test annotata con @WebMvcTest
(web test slice).
La documentazione di Spring Boot lo riassume molto bene:
Spesso
@WebMvcTest
sarà limitato a un singolo controller e utilizzato in combinazione con@MockBean
per fornire implementazioni simulate 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"));
}
}
@MockBean
sostituirà il bean nel contesto dell'applicazione se un bean che dichiara lo stesso tipo è già definito nella configurazione Spring. E l'iniezione viene eseguita nella classe in cui si dichiara @MockBean.
I meccanismi DI funzionano in questo modo: si registra un oggetto nel contesto DI e quindi si può iniettare l'oggetto a cui si fa riferimento nel contesto Spring in una classe specifica. Non iniettare un oggetto nel contesto DI.
Alla fine è facile da spiegare. Se guardi semplicemente nei javadocs delle annotazioni vedrai le differenze:
@Mock: ( org.mockito.Mock
)
Segna un campo come un finto.
- Consente la creazione di simulazioni stenografiche.
- Riduce al minimo il codice di creazione fittizia ripetitiva.
- Rende più leggibile la classe di test.
- Rende più semplice la lettura dell'errore di verifica perché il nome del campo viene utilizzato per identificare la simulazione.
@MockBean: ( org.springframework.boot.test.mock.mockito.MockBean
)
Annotazione che può essere utilizzata per aggiungere simulazioni a Spring ApplicationContext. Può essere utilizzato come annotazione a livello di classe o su campi in entrambe le
@Configuration
classi o classi di test che sono@RunWith
SpringRunner.I mock possono essere registrati per tipo o per nome del bean. Qualsiasi bean singolo esistente dello stesso tipo definito nel contesto verrà sostituito dal mock, se non viene definito un bean esistente, ne verrà aggiunto uno nuovo.
Quando
@MockBean
viene utilizzato su un campo, oltre ad essere registrato nel contesto dell'applicazione, il mock verrà anche iniettato nel campo.
Mockito.mock ()
È solo la rappresentazione di a
@Mock
.
@MockBean
e @Mock
che uno inietterà la derisione nel Spring ApplicationContext
e l'altro no?