W3docs

Introdução ao Teste em Java

Por que testes importam em Java, a pirâmide de testes e uma visão geral dos principais frameworks de teste em Java.

Testes automatizados são a forma de provar que o código faz o que você espera — e continuar provando isso à medida que o código muda. Em vez de executar o programa manualmente e inspecionar a saída visualmente, você escreve pequenos programas que exercitam o seu código e verificam os resultados automaticamente. Em Java, esse ecossistema é construído em torno de frameworks como JUnit e Mockito, mas as ideias fundamentais — arrange, act, assert — são simples o suficiente para escrever à mão. Este capítulo mapeia o panorama antes que os capítulos posteriores se aprofundem em cada ferramenta.

Por que testes automatizados importam

Um teste é uma verificação pequena e repetível de que um trecho de código se comporta corretamente. O benefício não está na primeira execução — está em todas as execuções seguintes. Uma vez que um comportamento é capturado em um teste, qualquer alteração que o quebre falha de forma imediata e ruidosa, em vez de aparecer como um bug em produção semanas depois. Testes também documentam a intenção: um teste bem nomeado diz o que o código deve fazer.

// A test names a behavior, runs the code, and asserts the outcome.
@Test
void addsTwoPositiveNumbers() {
    int result = Calculator.add(2, 3);
    assertEquals(5, result);   // fails the build if result != 5
}

O objetivo é feedback rápido. Um conjunto de testes verde significa que você pode refatorar com confiança; um vermelho aponta diretamente para o que quebrou.

A pirâmide de testes

Os testes são organizados em camadas, geralmente representadas como uma pirâmide. Testes unitários ficam na base: muitos deles, rápidos, cada um verificando uma classe ou método em isolamento. Testes de integração ficam no meio: menos, mais lentos, verificando que os componentes funcionam juntos (seu código mais um banco de dados, por exemplo). Testes end-to-end (E2E) ficam no topo: poucos, os mais lentos, conduzindo a aplicação inteira como um usuário faria.

NívelEscopoVelocidadeQuantidadeFerramentas Java
Unitáriouma classe/métodorápido (ms)muitosJUnit, AssertJ
Integraçãovários componentesmédioalgunsJUnit, Testcontainers
End-to-endsistema inteirolentopoucosSelenium, REST-assured

A forma importa: apoie-se nos testes unitários baratos e rápidos para a maior parte da cobertura, e reserve os testes E2E lentos e frágeis para um punhado de jornadas críticas do usuário.

O padrão arrange–act–assert

Quase todo teste, em qualquer framework, segue a mesma estrutura de três etapas. Arrange (preparar) as entradas e quaisquer dependências. Act (agir) chamando o código sob teste. Assert (verificar) que o resultado corresponde ao que você espera. Manter essas etapas visualmente separadas torna um teste fácil de ler e fácil de depurar quando falha.

@Test
void rejectsBlankUsername() {
    // Arrange
    UserService service = new UserService();

    // Act
    boolean valid = service.isValidUsername("   ");

    // Assert
    assertFalse(valid);
}

Uma asserção que falha lança uma exceção, o framework a registra, e a execução continua para o próximo teste — assim, um comportamento quebrado nunca oculta os outros.

JUnit, o executor padrão

JUnit é o framework de testes unitários de facto para Java. Você anota métodos com @Test, o JUnit os descobre por reflexão, executa cada um e reporta aprovação/falha. Asserções como assertEquals, assertTrue e assertThrows são auxiliares estáticos que reprovam o teste quando a expectativa não é atendida. Projetos reais executam o JUnit através de uma ferramenta de build (o plugin Surefire do Maven ou a tarefa test do Gradle), não manualmente.

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    @Test
    void dividesNumbers() {
        assertEquals(4, Calculator.divide(8, 2));
    }

    @Test
    void throwsOnDivideByZero() {
        assertThrows(ArithmeticException.class, () -> Calculator.divide(1, 0));
    }
}

Como não há JAR do JUnit nem ferramenta de build neste executor, o exemplo abaixo constrói a mesma ideia do zero — um pequeno harness que executa verificações nomeadas e contabiliza aprovações e falhas, exatamente o que @Test mais assertEquals fazem internamente.

java— editable, runs on the server

O que observar na execução:

  • Cada chamada a assertEquals é um caso de teste — prepara as entradas, age chamando add ou isBlank, e verifica o resultado — espelhando exatamente o que um método @Test do JUnit faz.
  • Uma verificação aprovada imprime PASS e uma reprovada imprime FAIL com os valores esperado e atual, que é o diagnóstico que as mensagens de asserção do JUnit fornecem.
  • O caso intencionalmente errado (expected 10 but got 5) mostra como é um teste vermelho: o harness continua executando as verificações restantes em vez de parar na primeira falha.
  • O resumo contabiliza 5 no total, 4 aprovados, 1 reprovado — o mesmo relatório de aprovação/falha que um executor de testes imprime ao final de uma execução.
  • Como um teste falhou, o programa termina com BUILD FAILURE, demonstrando por que um único teste quebrado deve quebrar o build inteiro na CI.

Como as peças se encaixam

As ferramentas de teste do Java se sobrepõem umas às outras, desde asserções brutas até integração completa com o build:

  1. Asserções (assertEquals, assertThrows) declaram o que deve ser verdadeiro.
  2. JUnit descobre e executa métodos @Test e reporta os resultados.
  3. Mockito fornece colaboradores falsos para que uma unidade possa ser testada em isolamento.
  4. Maven ou Gradle integra o conjunto de testes ao build, reprovando-o em qualquer teste vermelho.
  5. CI executa o build a cada push, para que código quebrado nunca chegue à branch principal.

Cada capítulo posterior trata de um degrau dessa escada — anotações e asserções do JUnit primeiro, depois mocking com Mockito, e depois integração dos testes com Maven e Gradle. Entender onde cada ferramenta se encaixa mantém toda a história de testes coerente.

Prática

Prática
No padrão arrange-act-assert, o que a etapa 'assert' faz?
No padrão arrange-act-assert, o que a etapa 'assert' faz?
Was this page helpful?