Por que seus testes Java quebram (e como corrigir isso)
Você escreveu o código perfeito. O serviço funciona, a lógica é impecável e os bugs só existem nos projetos alheios. Mas quando você executa os testes... Aqui, um erro de conexão com o BD; ali, uma API externa não responde; e num terceiro teste, um NullPointerException porque a configuração não foi carregada corretamente. Familiar?
O problema é que os testes clássicos dependem do ambiente externo. Banco de dados, serviços REST, sistema de arquivos — tudo isso torna os testes frágeis, lentos e imprevisíveis. A solução são objetos mock e fixtures. Não são apenas palavras da moda, mas ferramentas que transformam o caos em ordem.
Neste artigo, vamos entender como usar mock e fixtures corretamente em testes Java com exemplos reais. Você aprenderá a diferença entre stub e mock, como configurar fixtures para cenários complexos e por que o Mockito é seu melhor amigo. Vamos nessa!
Objetos Mock: Simulação sem dor
O que é um mock e para que serve?
Um objeto mock é uma imitação de um componente real que se comporta exatamente como você determinar. Em vez de subir um banco de dados ou chamar uma API externa, você cria um "falso" que retorna dados pré-definidos.
Imagine: você está testando um serviço que envia notificações por e-mail. Para um teste real, precisaria subir um servidor de e-mail, configurar SMTP, verificar a fila... Com um objeto mock, você simplesmente verifica se o serviço chamou o método de envio com os parâmetros corretos. Rápido, limpo e controlável.
Mock vs Stub: Qual a diferença?
Iniciantes frequentemente confundem esses conceitos. Vamos esclarecer de uma vez por todas:
- Stub — retorna dados fixos. Você diz: "Quando o método getUser() for chamado, retorne um objeto User com o nome 'João'". O stub não verifica quantas vezes foi chamado.
- Mock — não só retorna dados, mas também verifica o comportamento. Você pode dizer: "Garanta que o método sendEmail() foi chamado exatamente uma vez com um endereço específico".
Simplificando: stub é "me dê dados", mock é "me dê dados e verifique como estou sendo usado". Na prática, os objetos mock são mais usados, pois oferecem mais controle.
Escrevendo seu primeiro mock com Mockito
Mockito é a biblioteca mais popular para mocks em Java. Ela se integra com JUnit 5 e Spring Boot, e a sintaxe é tão simples que você a aprenderá em cinco minutos.
Suponha que você tenha um serviço OrderService que depende de um repositório OrderRepository. Em vez do repositório real, criaremos um mock:
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {
@Mock
private OrderRepository orderRepository;
@Test
void testCreateOrder() {
// Criando o objeto mock
OrderService orderService = new OrderService(orderRepository);
// Configurando o comportamento do mock
when(orderRepository.save(any(Order.class)))
.thenReturn(new Order(1L, "test@example.com", 100.0));
// Chamando o método sob teste
Order result = orderService.createOrder("test@example.com", 100.0);
// Verificando o resultado
assertThat(result.getId()).isEqualTo(1L);
// Verificando se o método save foi chamado exatamente uma vez
verify(orderRepository, times(1)).save(any(Order.class));
}
}
Neste exemplo, nós:
- Criamos um mock para
OrderRepositoryusando a anotação@Mock. - Configuramos que, ao chamar
save(), um pedido pré-criado deve ser retornado. - Verific