Criando mocks e escrevendo testes unitários com Junit 5

Marcos
5 min readApr 4, 2021

Em se falando de testes de software existem vários tipos de teste e cada um com seu objetivo. Falando em objetivos o desse texto é falar sobre uma maneira de escrever testes unitários em Java, fazendo uso do Junit 5 e do Mockito, esta última é uma ferramenta bem útil na hora de testar funcionalidades de forma isolada.

Primeiro ponto: qual é o objetivo de um teste unitário?

São testes que têm como objetivo testar a menor unidade de testes, pode ser uma função, ou melhor, um método em Java por exemplo. A ideia é testar entrada e saída e exceções que podem ser lançadas.

Mas qual é a real vantagem ?

Não dá pra falar que é garantir a nível de software o comportamento esteja adequado, mas sim que um determinado bloco de código esteja funcionando independentemente dos demais.

Mão na massa

Tenho esse repositório no github: https://github.com/mmarcosab/api-sor, é uma api simples em java, vou usar como exemplo aqui.

A primeira coisa a se fazer, é verificar se no pom.xml existem essas dependências:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.7.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.1</version>
<scope>test</scope>
</dependency>

Caso não exista, só colocar.

São dependências que auxiliam na execução dos testes unitários, mostrando resultados e erros que eventualmente acontecem.

Também é necessário colocar esses plugins:

<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.4</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
.. outros plugins
</plugins>
</build>

O surefire executa a etapa de testes unitários no build do programa e o jacoco mostra um relatório de testes com a cobertura do código.

Com isso ao executar um comando “mvn clean install” é possível executar os testes durante o build.

Agora, em test eu tenho o costume de espelhar os pacotes da aplicação para escrever testes das classes, se liga:

Vou começar a escrever um teste. Se liga nesse trecho de código:

Vou escrever um teste unitário para ele:

Teste simples né? Mas ao rodar uma surpresa aparece e o teste não passa ..

Eu poderia colocar aqui só um código pra funcionar, mas melhor entender o motivo desse null e como resolvê-lo, para isso o Mokito vai ser muito útil.

Primeiro eu coloquei um breakpoint no teste e usei o “Debug” ao invés do “Run”:

Feito isso podemos dar uma olhada nos objetos e olha o pedidoController nulo ..

Olhando a classe que quero testar, ela tem vários objetos que são injetados durante sua execução, exemplo:

Além de injetar esses objetos, devo instanciar a classe PedidoController. Mas a aplicação não vai subir, lembra que quero testar a menor unidade possível?

Poderia subir essa api usando a anotação @SpringBootTest, mas não é o que desejo, escolha minha.

Escolhi criar mocks dos objetos e instanciar a classe que será testada, para isso devo fazer isso aqui:

A anotação @BeforeEach faz com que antes de qualquer teste ser executado o método anotado com ela seja executado, e nesse caso os mocks sejam criados.

Com isso, posso rodar de novo e a conversa muda:

Daora né?

Mas pode ficar melhor, como saber se testou todo o método? Escrevi esse texto sobre jacoco há uns dias e ele mostra como olhar um relatório de testes, se liga:

Não estou testando exceções .. Mas calma, com os mocks a gente pode fazer isso usando isso aqui:

Nessa linha escrevi o seguinte: atire uma exceção do tipo Exception.class quando o método savePedidoSalao() com qualquer parâmetro for executado.

Só rodar o teste e sucesso, depois buildar a aplicação e olhar o relatório de testes:

top né?

Com o Mockito também é possível escrever testes para condições (ifs da vida) fazendo uso do when() entre várias outras coisas, se liga na quantidade de métodos:

Agora veja esse outro trecho de código:

O desafio aqui é escrever um teste que valide os dois retornos, vou começar a validar o retorno 1, se liga:

E o teste passou :

Mas no relatório só o primeiro if foi testado:

O Mockito ajuda a simular que houve um retorno desse get e a segunda condição será executada:

Fiz uso do when() para simular uma condição que fizesse outro trecho do meu código ser executado e o teste passou:

O relatório demonstra isso:

Essa é uma forma muito simples de uso dessas tecnologias, mas existem muitas abordagens para testes unitários em java com Spring Boot como o mockMvc para validar rotas de apis, @SpringBootTest para subir de fato a aplicação durante a execução dos testes. Qual usar? Vai do tempo disponível, da capacidade técnica, criticidade etc ..

Fico por aqui. Vlw. Flw.

--

--