⚡ 3.8 Mocks que Lançam Exceções

Sistemas robustos devem se recuperar de falhas de infraestrutura. O que acontece se o Banco de Dados estiver fora do ar ou o servidor de e-mail (SMTP) falhar durante o processamento de um leilão?

🏗️ Cenário: Resiliência no Encerramento

Imagine que o EncerradorDeLeilao agora deve enviar um e-mail. Se o e-mail falhar, o sistema deve continuar processando os outros leilões (Isolation of Failure).

📄 Código Resiliente (Java 17)

public void encerra() {
    var leiloes = dao.correntes();
    for (var leilao : leiloes) {
        try {
            if (comecouSemanaPassada(leilao)) {
                leilao.encerra();
                dao.atualiza(leilao);
                carteiro.envia(leilao); // Nova dependência
                total++;
            }
        } catch (Exception e) {
            // Logging e continuidade do fluxo
            System.err.println("Falha ao processar leilão: " + leilao.getId());
        }
    }
}

🧪 Simulando Falhas com Mockito 5

Para testar se o sistema realmente continua após um erro, instruímos o Mock a lançar uma exceção.

📄 Testando a Sobrevivência do Loop

@Test
void deveContinuarExecucaoMesmoSeUmComponenteFalhar() {
    var leilao1 = new CriadorDeLeilao().para("TV").naData(antiga).constroi();
    var leilao2 = new CriadorDeLeilao().para("Geladeira").naData(antiga).constroi();
 
    var daoMock = mock(LeilaoDao.class);
    var carteiroMock = mock(Carteiro.class);
 
    when(daoMock.correntes()).thenReturn(List.of(leilao1, leilao2));
 
    // ⚒️ FORÇANDO A FALHA: Lançar exceção no primeiro envio
    doThrow(new RuntimeException()).when(carteiroMock).envia(leilao1);
 
    var encerrador = new EncerradorDeLeilao(daoMock, carteiroMock);
    encerrador.encerra();
 
// ✅ Verifica que o segundo leilão foi processado com sucesso
verify(daoMock).atualiza(leilao2);
verify(carteiroMock).envia(leilao2);

assertThat(encerrador.getTotalEncerrados()).isEqualTo(1);

}

---
 
## 📊 Estratégias de Exceção no Mockito
 
| Tipo de Invocação | Sintaxe de Elite |
| :--- | :--- |
| **Métodos com Retorno** | `when(...).thenThrow(new RuntimeException())` |
| **Métodos Void** | `doThrow(new Exception()).when(mock).metodo()` |
| **Estilo BDD** | `willThrow(new Exception()).given(mock).metodo()` |
 
> [!CAUTION] Catch-All 🛡️
> 
> Capturar `Exception` de forma genérica é aceitável em loops de processamento em lote (Batch), mas certifique-se de que o erro seja logado adequadamente para análise técnica posterior. 🏁

⬅️ Capítulo Anterior | Próximo Capítulo ➡️