⏱️ 3.10 Isolando o Tempo com java.time.Clock

Sistemas reais dependem do tempo, mas o tempo é o maior inimigo da estabilidade dos testes. Se o seu código usa LocalDate.now(), o teste pode passar hoje e falhar amanhã. Na Engenharia de Elite, abstraímos o relógio.

🏗️ O Problema do Relógio Estático

Códigos que chamam o sistema operacional diretamente são “Caixas Pretas”. Para torná-los determinísticos, devemos injetar um Relógio (Clock).

📄 Implementação Premium (Java 17)

Em vez de criar interfaces customizadas, o Java 8+ já fornece o java.time.Clock, que é perfeitamente integrado com a API de datas.

public class GeradorDePagamento {
    private final Clock clock; // ✅ Abstração nativa do Java
 
    public GeradorDePagamento(Clock clock, ...) {
        this.clock = clock;
    }
 
    public void gera() {
        // ... lógica ...
        var hoje = LocalDate.now(clock); // ✅ Agora o 'hoje' é controlável!
        var pagamento = new Pagamento(valor, proximoDiaUtil(hoje));
    }
}

🧪 O Teste Determinístico (Freezing Time)

No Mockito, podemos injetar um relógio “congelado” em qualquer data específica para validar regras como feriados ou fins de semana.

@Test
void deveEmpurrarParaSegundaSeForSabado() {
    // 🥶 Congelando o tempo no Sábado, 07/Abril/2012
    var sabadoExato = Instant.parse("2012-04-07T10:00:00Z");
    var clockMock = Clock.fixed(sabadoExato, ZoneId.of("UTC"));
 
    var gerador = new GeradorDePagamento(clockMock, ...);
    gerador.gera();
 
    // Captura e validação...
    assertThat(pagamento.getData()).isEqualTo("2012-04-09"); // Segunda-feira
}

Injeção de Relógio 🛡️

Ao adotar o Clock, você ganha o superpoder de viajar no tempo em seus testes. Isso elimina 100% dos testes flutuantes (flaky tests) causados por viradas de dia, ano bissexto ou fusos horários. 🚀


Dica de Ouro ⚡

No Spring Boot, você pode declarar um @Bean de Clock.systemDefaultZone() e injetá-lo em seus serviços. Nos testes, basta substituir por Clock.fixed(). 🏁


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