🧪 1.19 Testando Exceções sob Pressão
Arquiteturas resilientes devem prever o fracasso. O tratamento de cenários excepcionais é tão vital quanto o fluxo de sucesso. No nosso leilão, o que acontece se tentarmos avaliar um pregão sem lances?
🏗️ Implementando a Proteção de Negócio
Validamos o estado antes do processamento. Se não houver lances, interrompemos o fluxo com uma exceção clara:
public void avalia(Leilao leilao) {
if (leilao.getLances().isEmpty()) {
throw new IllegalArgumentException("Não é possível avaliar um leilão sem lances!");
}
// ... lógica de avaliação ...
}🛠️ Estratégias Modernas de Teste (JUnit 5 + AssertJ)
O JUnit 5 aposentou o atributo (expected = ...) do JUnit 4 em favor de uma abordagem funcional muito mais poderosa e flexível.
🏁 Abordagem Jupiter: assertThrows
A forma nativa do JUnit 5 utiliza lambdas para capturar a exceção e permitir validações posteriores:
@Test
void naoDeveAvaliarLeilaoSemLances() {
var leilao = new CriadorDeLeilao().para("Playstation 5").constroi();
var excecao = assertThrows(IllegalArgumentException.class, () -> {
leiloeiro.avalia(leilao);
});
// Validando a mensagem da exceção
assertEquals("Não é possível avaliar um leilão sem lances!", excecao.getMessage());
}🏆 Abordagem de Elite: AssertJ assertThatThrownBy
Para máxima legibilidade, o AssertJ oferece uma sintaxe fluída que descreve exatamente o que se espera:
@Test
void deveLancarExcecaoParaLeilaoSemLances() {
var leilao = new CriadorDeLeilao().para("Playstation 5").constroi();
assertThatThrownBy(() -> leiloeiro.avalia(leilao))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("sem lances");
}📊 Comparativo Técnico
| Recurso | JUnit 4 (Legacy) | JUnit 5 / AssertJ (Moderno) |
|---|---|---|
| Sintaxe | Atributo @Test(expected) | Funcional (Lambdas) |
| Precisão | Fraca (qualquer linha pode falhar) | Alta (apenas o bloco lambda é vigiado) |
| Validação da Mensagem | Difícil (exige try-catch manual) | Nativa e fluída |
Use o Padrão Moderno 🛡️
Evite o uso de
try-catchem testes. As ferramentas modernas (assertThrowsouassertThatThrownBy) garantem que o teste falhe corretamente se a exceção NÃO for lançada, eliminando a necessidade deAssert.fail(). 🏁