Testes em Java: unit, integration, e2e — guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Testes em Java: de unitários a testes de ponta a ponta



A qualidade do código é um dos principais indicadores de profissionalismo de um desenvolvedor. No mundo Java, os testes há muito deixaram de ser apenas uma boa prática e se tornaram um padrão da indústria. Sem testes confiáveis, é difícil manter grandes projetos, implementar novos recursos e refatorar o código com confiança. Neste artigo, vamos analisar três níveis principais de teste: unit (unitário), integration (integração) e e2e (ponta a ponta). Você aprenderá como eles diferem, como escrevê-los corretamente em Java e quais ferramentas usar.



A pirâmide de testes e por que ela é importante

Antes de nos aprofundarmos nos detalhes, vale a pena lembrar o conceito da pirâmide de testes (Mike Cohn). Ela visualiza a proporção ideal de testes em diferentes níveis:

  • Testes unitários (base da pirâmide) — os mais rápidos, baratos e numerosos. Devem representar cerca de 70%.
  • Testes de integração (meio) — verificam a interação entre componentes. Cerca de 20%.
  • Testes E2E (topo) — os mais lentos e caros, mas criticamente importantes para verificar cenários de usuário. Cerca de 10%.

Seguir essa proporção permite obter o máximo de confiança no código com o mínimo de tempo gasto na execução dos testes.



1. Testes unitários em Java

Testes unitários verificam isoladamente uma "unidade" de código — geralmente um método ou classe. Seu principal objetivo é garantir que a lógica do método funcione corretamente, independentemente de dependências externas (banco de dados, API, sistema de arquivos). Para o isolamento, são usados mock objects.



Ferramentas principais

  • JUnit 5 — framework padrão para escrever testes.
  • Mockito — biblioteca para criar mock objects e verificar interações.
  • AssertJ — biblioteca para asserções fluidas (aumenta a legibilidade).


Exemplo de teste unitário com JUnit 5 e Mockito

Suponha que temos um serviço UserService que depende de UserRepository:

public class UserService {    private final UserRepository repository;        public UserService(UserRepository repository) {        this.repository = repository;    }        public User findById(Long id) {        return repository.findById(id)                .orElseThrow(() -> new UserNotFoundException("User not found"));    }}

Teste para este método:

import org.junit.jupiter.api.Test;import org.junit.jupiter.api.extension.ExtendWith;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.junit.jupiter.MockitoExtension;import java.util.Optional;import static org.junit.jupiter.api.Assertions.*;import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)class UserServiceTest {

@Mock private UserRepository repository;

@InjectMocks private UserService userService;

@Test void testFindById_UserExists() { // Given Long userId = 1L; User expectedUser = new User(userId, "Alice"); when(repository.findById(userId)).thenReturn(Optional.of(expectedUser));

// When User actualUser = userService.findById(userId);

// Then assertNotNull(actualUser); assertEquals("Alice", actualUser.getName()); verify(repository).findById(userId); }

@Test void testFindById_UserNotFound() { // Given Long userId = 99L; when(repository.findById(userId)).thenReturn(Optional.empty());

// When & Then assertThrows(UserNotFoundException.class, () -> userService.findById(userId)); }}

Best practices:

  • Teste apenas u

Blogs

Book Recommendations