Mockito - Usando espiões

Mockito - Usando espiões

1. Visão geral

Neste tutorial, ilustraremos como aproveitar ao máximospies in Mockito.

Falaremos sobre a anotação@Spy, como stubar um espião e, finalmente - entraremos na diferença entreMockeSpy.

E, claro, para obter mais vantagens do Mockito,have a look at the series here.

Leitura adicional:

Livro de receitas do Mockito Verifique

Mockito Verify exemplos, uso e melhores práticas.

Read more

Injeção de mockock Mockito nos feijões da primavera

Este artigo mostrará como usar a injeção de dependência para inserir zombarias Mockito no Spring Beans para teste de unidade.

Read more

Métodos de simulação de Mockito

Este tutorial ilustra vários usos dos métodos de simulação estáticos padrão da API do Mockito.

Read more

2. Exemplo deSpy simples

Vamos começar com um exemplo simples dehow to use a spy.

Simplificando, a API éMockito.spy() - aspy on a real object.

Isso nos permitirá chamar todos os métodos normais do objeto enquanto ainda rastreamos todas as interações, da mesma forma que chamaríamos com uma simulação.

OK, vamos fazer um exemplo rápido em que espionaremos um objetoArrayList existente:

@Test
public void whenSpyingOnList_thenCorrect() {
    List list = new ArrayList();
    List spyList = Mockito.spy(list);

    spyList.add("one");
    spyList.add("two");

    Mockito.verify(spyList).add("one");
    Mockito.verify(spyList).add("two");

    assertEquals(2, spyList.size());
}

Observe comothe real method add() is actually called e como o tamanho despyList se torna 2.

3. A anotação@Spy

A seguir - vamos ver como usar a anotação@Spy. Podemos usar a anotação@Spy em vez despy() como no exemplo a seguir:

@Spy
List spyList = new ArrayList();

@Test
public void whenUsingTheSpyAnnotation_thenObjectIsSpied() {
    spyList.add("one");
    spyList.add("two");

    Mockito.verify(spyList).add("one");
    Mockito.verify(spyList).add("two");

    assertEquals(2, spyList.size());
}

Paraenable Mockito annotation (como@Spy,@Mock, ...) - precisamos fazer um dos seguintes:

  • Chame o métodoMockitoAnnotations.initMocks(this) para inicializar os campos anotados

  • Use o runner integrado@RunWith(MockitoJUnitRunner.class)

4. Stubbing aSpy

Agora - vamos ver como criar um esboço deSpy. Podemos configurar / substituir o comportamento de um método usando a mesma sintaxe que usaríamos com uma simulação.

No exemplo a seguir - usamosdoReturn() para substituir o métodosize():

@Test
public void whenStubASpy_thenStubbed() {
    List list = new ArrayList();
    List spyList = Mockito.spy(list);

    assertEquals(0, spyList.size());

    Mockito.doReturn(100).when(spyList).size();
    assertEquals(100, spyList.size());
}

5. Mock vs. Spy in Mockito

Agora - vamos discutir a diferença entreMockeSpy no Mockito - não as diferenças teóricas entre os dois conceitos, apenas como eles diferem dentro do próprio Mockito.

Quando o Mockito cria um mock - ele o faz a partir deClass de um Type, não de uma instância real. A simulação simplesmente criaa bare-bones shell instance da Classe, inteiramente instrumentada para rastrear interações com ela.

Por outro lado,the spy will wrap an existing instance. Ele ainda se comportará da mesma maneira que a instância normal - a única diferença é que ele também será instrumentado para rastrear todas as interações com ele.

No exemplo a seguir - criamos ummock da classeArrayList:

@Test
public void whenCreateMock_thenCreated() {
    List mockedList = Mockito.mock(ArrayList.class);

    mockedList.add("one");
    Mockito.verify(mockedList).add("one");

    assertEquals(0, mockedList.size());
}

Como podemos ver - adicionar um elemento na lista simulada não adiciona nada - ele apenas chama o método sem nenhum outro efeito colateral.

Por outro lado, um espião se comportará de maneira diferente - ele realmente chamará a implementação real do métodoadd e adicionará o elemento à lista subjacente:

@Test
public void whenCreateSpy_thenCreate() {
    List spyList = Mockito.spy(new ArrayList());

    spyList.add("one");
    Mockito.verify(spyList).add("one");

    assertEquals(1, spyList.size());
}

6. Compreendendo o MockitoNotAMockException

Nesta seção final, aprenderemos sobre o MockitoNotAMockException. This exception is one of the common exceptions we will likely encounter when misusing mocks or spies.

Vamos começar vendo em que circunstância essa exceção pode ocorrer:

List list = new ArrayList();
Mockito.doReturn(100).when(list).size();

assertEquals("Size should be 100: ", 100, list.size());

Quando executamos este snippet de código, obteremos o seguinte erro:

org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!
Example of correct stubbing:
    doThrow(new RuntimeException()).when(mock).someMethod();

Felizmente, é claro na mensagem de erro do Mockito qual é o problema aqui. Em nosso exemplo, o objetolist não é uma simulação. The Mockito when() method expects a mock or spy object as the argument.

Como também podemos ver, a mensagem Exceção descreve como deve ser a chamada correta. Agora que entendemos melhor qual é o problema, vamos corrigi-lo seguindo a recomendação:

final List spyList = Mockito.spy(new ArrayList());
Mockito.doReturn(100).when(spyList).size();

assertEquals("Size should be 100: ", 100, spyList.size());

Nosso exemplo agora se comporta como esperado e não vemos mais o MockitoNotAMockException.

7. Conclusão

Neste artigo rápido, discutimos os exemplos mais úteis do uso de espiões do Mockito.

Aprendemos como criar umspy, como usar a anotação@Spy, como esboçar umspye, finalmente - a diferença entreMockeSpy.

A implementação de todos esses exemploscan be found over on GitHub.

Como é um projeto do Maven, deve ser fácil importar e executar como está.

E, claro, para obter mais vantagens do Mockito,have a look at the series here.