Ao criar testes e zombar de dependências, qual é a diferença entre essas três abordagens?
@MockBean:
@MockBean MyService myservice;
@Zombar:
@Mock MyService myservice;
Mockito.mock ()
MyService myservice = Mockito.mock(MyService.class);
Biblioteca simples de Mockito
import org.mockito.Mock;
...
@Mock
MyService myservice;
e
import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);
provêm da biblioteca Mockito e são funcionalmente equivalentes.
Eles permitem zombar de uma classe ou interface e registrar e verificar comportamentos nela.
A maneira como a anotação é mais curta, é preferível e geralmente preferida.
Observe que, para ativar as anotações do Mockito durante as execuções de teste, o
MockitoAnnotations.initMocks(this)
método estático deve ser chamado.
Para evitar efeitos colaterais entre os testes, é recomendável fazê-lo antes de cada execução de teste:
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
Outra maneira de ativar as anotações do Mockito é fazer anotações na classe de teste @RunWith
especificando o MockitoJUnitRunner
que executa esta tarefa e também outras coisas úteis:
@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}
Biblioteca Spring Boot envolvendo a biblioteca Mockito
Esta é realmente uma classe Spring Boot :
import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
A classe está incluída na spring-boot-test
biblioteca.
Permite adicionar zombarias de Mockito em uma mola ApplicationContext
.
Se um bean compatível com a classe declarada existir no contexto, ele será substituído pelo mock.
Se não for o caso, ele adiciona a simulação no contexto como um bean.
Referência Javadoc:
Anotação que pode ser usada para adicionar zombarias a um Spring ApplicationContext.
...
Se qualquer bean único existente do mesmo tipo definido no contexto for substituído pelo mock, se nenhum bean existente for definido, um novo será adicionado.
Quando usar o Mockito clássico / comum e quando usar o @MockBean
Spring Boot?
Os testes de unidade são projetados para testar um componente isoladamente de outros componentes e os testes de unidade também têm um requisito: ser o mais rápido possível em termos de tempo de execução, pois esses testes podem ser executados diariamente dezenas de vezes nas máquinas do desenvolvedor.
Consequentemente, aqui está uma diretriz simples:
Ao escrever um teste que não precisa de nenhuma dependência do contêiner Spring Boot, o Mockito clássico / comum é o caminho a seguir: é rápido e favorece o isolamento do componente testado.
Se o seu teste precisar contar com o contêiner Spring Boot e você também quiser adicionar ou simular um dos beans do contêiner: a @MockBean
partir do Spring Boot é o caminho.
Uso típico do Spring Boot @MockBean
Enquanto escrevemos uma classe de teste anotada com @WebMvcTest
(fatia de teste da web).
A documentação do Spring Boot resume muito bem isso:
Freqüentemente
@WebMvcTest
será limitado a um único controlador e usado em conjunto@MockBean
para fornecer implementações simuladas para os colaboradores necessários.
Aqui está um exemplo :
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
substituirá o bean no contexto do aplicativo se um bean que declara o mesmo tipo já estiver definido na sua configuração do Spring. E a injeção é realizada na classe em que você declara@MockBean.
Os mecanismos de DI funcionam desta maneira: você registra um objeto no contexto de DI e pode injetar o objeto referenciado no contexto de Spring em uma classe específica. Você não injeta um objeto no contexto de DI.No final, é fácil de explicar. Se você apenas olhar para os javadocs das anotações, verá os diferentes:
@Mock: (
org.mockito.Mock
)@MockBean: (
org.springframework.boot.test.mock.mockito.MockBean
)Mockito.mock ()
fonte
@MockBean
e@Mock
que um injetará o escárnio noSpring ApplicationContext
outro e o outro não?