Testar software é uma etapa crucial no desenvolvimento de aplicações. Testes unitários garantem que partes individuais do código funcionem conforme o esperado. Neste artigo, vamos explorar um exemplo de código que utiliza o framework de testes JUnit 5 e a biblioteca Mockito para testar uma classe chamada PlanetServices.
Entendendo o Código de Teste
O código de teste em questão é responsável por testar os métodos da classe PlanetServices. Essa classe oferece serviços relacionados a planetas, um crud básico: criar, buscar, listar planetas, deletar.
Código fonte da aplicação:
Antes da criação dos testes, crie um pacote a parte para criarmos uma classe com duas constantes para usarmos nos testes, exemplo abaixo:
O teste começa importando várias classes e métodos estáticos de bibliotecas, como org.assertj.core.api.Assertions e org.mockito.Mockito. Essas importações são usadas para fazer asserções nos testes e configurar comportamentos simulados.
A anotação @ExtendWith(MockitoExtension.class) na classe de teste indica que a extensão Mockito será usada para fornecer suporte a objetos simulados (mocks).
A anotação @InjectMocks é usada para injetar automaticamente os objetos simulados criados com @Mock na classe de teste. No exemplo, a classe PlanetServices será injetada com o mock PlanetRepository.
Testando a Criação de Planetas
Vamos analisar o primeiro teste:
A configuração when(planetRepository.save(PLANET)).thenReturn(PLANET) diz que, quando o método save do mock planetRepository for chamado com o argumento PLANET, ele deve retornar o próprio PLANET.
A chamada planetServices.create(PLANET) invoca o método create da classe PlanetServices com o objeto PLANET, e o resultado é atribuído à variável sut.
A asserção assertThat(sut).isEqualTo(PLANET) verifica se o objeto retornado é igual ao objeto esperado PLANET.
Testando a Criação de Planetas com Dados Inválidos
O próximo teste aborda um cenário em que a criação de um planeta com dados inválidos leva a uma exceção:
A configuração when(planetRepository.save(INVALID_PLANET)).thenThrow(RuntimeException.class) instrui o mock planetRepository a lançar uma exceção do tipo RuntimeException quando o método save for chamado com INVALID_PLANET.
A expressão assertThatThrownBy(() -> planetServices.create(INVALID_PLANET)).isInstanceOf(RuntimeException.class) verifica se a chamada ao método create com INVALID_PLANET lança uma exceção do tipo esperado
Buscando um Planeta por ID Existente
O próximo teste lida com a busca de um planeta por um ID existente:
A configuração when(planetRepository.findById(1L)).thenReturn(Optional.of(PLANET)) diz que, quando o método findById do mock planetRepository for chamado com o argumento 1L, ele deve retornar um Optional contendo o objeto PLANET.
A chamada planetServices.findById(1L) invoca o método findById da classe PlanetServices com o ID 1L. O resultado é atribuído a sut, um Optional de Planet.
As asserções verificam se o Optional não está vazio e se o objeto contido nele é igual a PLANET.
Buscando um Planeta por ID Inexistente
O próximo teste testa a busca de um planeta por um ID que não existe:
A configuração when(planetRepository.findById(1L)).thenReturn(Optional.empty()) diz que, quando o método findById do mock planetRepository for chamado com o argumento 1L, ele deve retornar um Optional vazio.
A chamada planetServices.findById(1L) invoca o método findById da classe PlanetServices com o ID 1L. O resultado é atribuído a sut, um Optional de Planet.
A asserção verifica se o Optional está vazio.
Buscando um Planeta por Nome Existente
O teste a seguir lida com a busca de um planeta por um nome existente.
A configuração when(planetRepository.findByName("Tatooine")).thenReturn(Optional.of(PLANET)) instrui o mock planetRepository a retornar um Optional contendo o objeto PLANET quando o método findByName for chamado com o argumento "Tatooine".
A chamada planetServices.findByName("Tatooine") invoca o método findByName da classe PlanetServices com o nome "Tatooine". O resultado é atribuído a sut, um Optional de Planet.
As asserções verificam se o Optional não está vazio e se o objeto contido nele é igual a PLANET.
Buscando um Planeta por Nome Inexistente
Este teste verifica a busca de um planeta por um nome que não existe:
A configuração when(planetRepository.findByName(name)).thenReturn(Optional.empty()) instrui o mock planetRepository a retornar um Optional vazio quando o método findByName for chamado com o argumento name.
A chamada planetServices.findByName(name) invoca o método findByName da classe PlanetServices com o nome especificado. O resultado é atribuído a sut, um Optional de Planet.
A asserção verifica se o Optional está vazio.
Listando Planetas
Os testes a seguir abordam a listagem de planetas com base em diferentes cenários.
Testando a listagem de todos os planetas:
Uma lista planets é criada com um planeta PLANET adicionado a ela.
É criado um exemplo de consulta query usando a classe QueryBuilder com base nas propriedades do objeto PLANET.
A configuração
when(planetRepository.findAll(query)).thenReturn(planets) instrui o mock planetRepository a retornar a lista de planetas quando o método findAll for chamado com a query especificada.A chamada planetServices.list(PLANET.getTerrain(), PLANET.getClimate()) invoca o método list da classe PlanetServices com os parâmetros de terreno e clima do planeta.
As asserções verificam se a lista retornada não está vazia, se possui um único elemento e se esse elemento é igual ao objeto PLANET.
Testando a listagem vazia de planetas:
A configuração when(planetRepository.findAll((Example) any())).thenReturn(Collections.emptyList()) instrui o mock planetRepository a retornar uma lista vazia quando o método findAll for chamado com qualquer argumento.
A chamada planetServices.list(PLANET.getTerrain(), PLANET.getClimate()) invoca o método list da classe PlanetServices com os parâmetros de terreno e clima do planeta.
A asserção verifica se a lista retornada está vazia.
Removendo Planetas por ID
Testando a remoção de um planeta com ID existente:
- A expressão assertThatCode(() -> planetServices.deletePlanet(1L)).doesNotThrowAnyException() verifica se a chamada ao método deletePlanet com o ID 1L não lança nenhuma exceção.
Testando a remoção de um planeta com ID inexistente:
A configuração doThrow(new RuntimeException()).when(planetRepository).deleteById(99L) instrui o mock planetRepository a lançar uma exceção do tipo RuntimeException quando o método deleteById for chamado com o argumento 99L.
A expressão assertThatThrownBy(() -> planetServices.deletePlanet(99L)).isInstanceOf(RuntimeException.class) verifica se a chamada ao método deletePlanet com o ID 99L lança uma exceção do tipo esperado.
Conclusão
Neste artigo, exploramos um conjunto abrangente de testes unitários que cobrem diferentes cenários de uso da classe PlanetServices.
Usando o JUnit 5 e o Mockito, conseguimos testar a criação, busca, listagem e remoção de planetas em um ambiente controlado.
A prática de escrever testes robustos não apenas ajuda a identificar problemas de código, mas também proporciona confiança na qualidade do software produzido.
O uso conjunto do JUnit 5 e do Mockito demonstra como realizar testes eficazes em ambientes de desenvolvimento Java.
Top comments (0)