Pessoal, lembram do desafio daquele módulo Programação Orientada a Objetos com Java chamado Abstraindo um Bootcamp Usando Orientação a Objetos em Java. Bom eu resolvi aplicar o framework Junit e Mockito para construir os testes unitários deste projeto. Uma premissa que eu assumi ao desenvolver o código, fiz de conta que era legado, ou seja eu iria construir os testes em torno do projeto e não refatorar o projeto em torno dos testes (metodologia TDD). Antes de irmos adiante eu queria explicar um pouco do que se trata o Mockito.

Para relembrar do que se trata o Junit, é um framework que provê ferramentas para testes unitários na linguagem Java, mais detalhes aqui → https://pt.wikipedia.org/wiki/JUnit

Já o framework Mockito é uma espécia de “enganador”, ele implementa uma estrutura que eu configuro via anotations e métodos estáticos que isola o bloco de código que eu estou validando, simulando chamadas e retornos.

Por exemplo, veja a figura 1 abaixo:

FIGURA 1

FIGURA 1

Eu estou querendo testar os métodos da camada de serviço (onde estão implementadas as regras de negócio do modelo), mas quero simular as chamadas dentro destes métodos feitas a camada repositório (que são os métodos que efetivamente acessam o banco de dados). Para isso eu “engano” a camada de serviço interceptando essas chamadas e enviando uma resposta previamente definida. Dessa forma eu isolo o problema e garanto que se houver algo errado, esse erro não está localizado fora do meu bloco de código domínio do teste unitário.

A anotação @Mock cria uma instância da classe ProductRepository “mockeando” os métodos pertinentes, a anotação @InjectMocks cria uma instancia da classe cujo os métodos quero testar e injeta os “mocks” criados por @Mock nesta instância. Bom como muitos instrutores da Dio falam, “Show me f* code” (O f* é de minha autoria 😄).

Eu vou a seguir transcrever um trecho de código de um pacote de testes unitários que fiz para testar a camada de serviço associada a uma entidade (Produto) em um projeto usando REST API no Spring Boot.

Primeiro eu crio os mocks e defino a classe que quero injetar os mesmos usando @InjectMocks.

  @InjectMocks
	private ProductService service;

	@Mock
	private ProductRepository productRepository;

A seguir eu defino o que eu quero simular da classe mockada, no caso o método produtRepository.findById (que é chamado pelo método findById() da classe ProductService ) usando método estático when()…thenReturn()

Mockito.when(productRepository.findById(productExistingId)).thenReturn(Optional.of(product));

E no teste propriamente dito, usando outro método estático fornecido pelo Mockito verify() , valido se o método foi executado sem problemas e também verifico o número de vezes que o método dummy foi chamado (no caso, espera-se que seja chamado uma única vez, caso contrário o teste falha) :

@DisplayName("003 - findById should return ProductDTO when product id exists.")	
@Test
	public void findByIdShouldReturnProductDTOWhenIdExists() {
		
		ProductDTO result = service.findById(productExistingId);
		
		Assertions.assertNotNull(result);
		
		Mockito.verify(productRepository,Mockito.times(1)).findById(productExistingId);
		
	}

Veja que para o método da classe Service isso tudo é transparente, mas na realidade o banco de dados nunca foi acessado, a resposta esperada pelo método foi injetada pelo método dummy criado pelo Mockito.

Bom acho que já deu pra ter uma ideia né. Então vamos a implementação que fiz no projeto desafio POO. Eu implementei 7 testes no total: