📚 Pré-requisitos Teóricos: este projeto aplica conceitos ensinados em Especialização em Backend com Java e Spring Boot. Recomendado revisar antes de começar.
Este guia é a continuação do projeto Biblioteca de Jogos (Módulo 5 do nosso plano de expansão). Aqui, vamos aprender a garantir a qualidade do nosso código através de Testes Unitários usando o framework JUnit 5 e a biblioteca de simulação Mockito.
@Mock, @InjectMocks, @BeforeEach, @Test.pom.xmlPara começar a testar, precisamos garantir que temos as dependências corretas. Se você usou o Spring Initializr para criar o projeto do Módulo 1, a dependência spring-boot-starter-test já deve estar incluída. Ela traz o JUnit 5 e o Mockito juntos!
Abra o arquivo pom.xml e verifique se este bloco está presente:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Por padrão no Maven, o código-fonte fica em src/main/java e os testes ficam em src/test/java.
Vamos criar a mesma estrutura de pacotes para os testes para manter a organização.
Crie o arquivo JogoServiceTest.java no seguinte caminho:
src/test/java/br/com/bibliotecajogos/service/JogoServiceTest.java
Vamos testar o método buscarPorId do JogoService. Queremos garantir que, quando o repositório encontra um jogo, o serviço retorna esse jogo corretamente.
package br.com.bibliotecajogos.service;
import br.com.bibliotecajogos.entity.Jogo;
import br.com.bibliotecajogos.repository.JogoRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
public class JogoServiceTest {
// 1. Cria um "dublê" do repositório. Ele não acessará o banco de dados de verdade.
@Mock
private JogoRepository jogoRepository;
// 2. Cria uma instância real do serviço e injeta o repositório mockado nele.
@InjectMocks
private JogoService jogoService;
@BeforeEach
void setUp() {
// Inicializa as anotações do Mockito para esta classe de teste
MockitoAnnotations.openMocks(this);
}
@Test
void deveRetornarJogoQuandoIdExiste() {
// --- CENÁRIO (Given) ---
Long idExistente = 1L;
Jogo jogoEsperado = new Jogo();
jogoEsperado.setId(idExistente);
jogoEsperado.setTitulo("Zelda: Ocarina of Time");
// Ensinamos o Mock: "Quando chamarem findById(1), retorne o jogo do Zelda"
when(jogoRepository.findById(idExistente)).thenReturn(Optional.of(jogoEsperado));
// --- AÇÃO (When) ---
Jogo jogoRetornado = jogoService.buscarPorId(idExistente);
// --- VERIFICAÇÃO (Then) ---
// Verificamos se o resultado não é nulo
assertNotNull(jogoRetornado);
// Verificamos se o título é exatamente o que esperávamos
assertEquals("Zelda: Ocarina of Time", jogoRetornado.getTitulo());
// Verificamos se o método do repositório foi chamado exatamente 1 vez
verify(jogoRepository, times(1)).findById(idExistente);
}
}
E se o jogo não existir no banco? O método deve retornar null. Vamos testar esse comportamento para garantir que nosso código lida bem com falhas.
Adicione este método de teste à classe JogoServiceTest:
@Test
void deveRetornarNullQuandoIdNaoExiste() {
// --- CENÁRIO ---
Long idNaoExiste = 99L;
// Ensinamos o Mock: "Quando buscarem por 99, retorne vazio"
when(jogoRepository.findById(idNaoExiste)).thenReturn(Optional.empty());
// --- AÇÃO ---
Jogo jogoRetornado = jogoService.buscarPorId(idNaoExiste);
// --- VERIFICAÇÃO ---
// Esperamos que o retorno seja nulo
assertNull(jogoRetornado);
// Verificamos se a busca foi feita no repositório
verify(jogoRepository, times(1)).findById(idNaoExiste);
}
@Mock: Esta anotação diz ao Mockito para criar uma “casca” vazia do objeto. Ele tem os mesmos métodos, mas eles não fazem nada a menos que você os ensine. Isso é crucial porque testes unitários não devem tocar no banco de dados.@InjectMocks: Esta anotação cria a instância da classe que você quer testar e tenta injetar nela todos os mocks que você declarou com @Mock.when(...).thenReturn(...): É o coração do Mockito. Como o mock não tem comportamento próprio, você precisa dizer a ele o que fazer. É como dar um script para um ator.assertEquals(esperado, atual): Método do JUnit que compara dois valores. Se forem diferentes, o teste “falha” e avisa o desenvolvedor.verify(mock, vezes): Garante que uma determinada ação aconteceu. É útil para testar se o fluxo do código passou por onde deveria.Agora que você viu como testar a busca, tente escrever os testes para o método salvar(Jogo jogo) e excluir(Long id).
Dica: Para o salvar, você usará when(jogoRepository.save(jogo)).thenReturn(jogo);.
—`
No seu editor/IDE, abra a pasta deste projeto (File > Open Folder) ou navegue via terminal:
cd javaweb_jogos_guia_testes
./mvnw spring-boot:run
./mvnw test
[!TIP] Dica para execução a partir da raiz do repositório: Se você abriu o repositório completo no VS Code, basta navegar até a pasta antes de executar: cd proj_aplicacoes_full_stack/projetos/javaweb_jogos_guia_testes