De volta para o futuro: usando Clock para manipular o tempo nos seus testes

Dherik Barison
CWI Software
Published in
3 min readDec 14, 2019

Conhecer a linguagem de programação muitas vezes não é só essencial para criar um bom código mas também para criar bons testes.

Um destes conhecimentos que pode ser estranho para uma parte significativa dos desenvolvedores Java 8+ é a classe Clock.

Voltar no tempo com Java é bem mais simples

A classe Clock é responsável por providenciar o tempo atual, que no Java é chamado de instante (instant). Quando fazemos, por exemplo, um LocalDate.now(), o Java lê o instante do relógio do seu computador. Porém, podemos manipular este instante colocando um Clock diferente no lugar dele.

Usando o exemplo do LocalDate.now(), podemos “enganá-lo” quanto ao instante em que ele está, bastando passar um Clock para o método now() como parâmetro, da seguinte forma: LocalDate.now(clock).

Agora, como posso manipular o tempo (ou instante) com o Clock?

Existem diferentes maneiras. Uma das mais simples é esta:

Porém, isto levanta questões práticas de como usá-lo:

  • Como passar o Clock para o método now() em um projeto de verdade?
  • Como alternar o instante real com o instante que quero no meu teste?

A melhor prática e oficialmente recomendada para lidar com este cenário é usar a injeção de dependência por construtor, assunto este já abordado em outro texto.

Basicamente, você cria o objeto Clock como uma dependência injetável e passa para dentro do construtor da classe. Isto vai permitir que o Clock seja injetado pelo seu framework de injeção e, para o teste unitário, permitirá ao desenvolvedor instanciar o Clock com o instante no tempo que preferir.

Usando…

Vamos mostrar abaixo um exemplo de como conseguimos montar este cenário todo usando o framework Spring.

Sua classe que receberá a injeção de Clock ficaria assim:

O teste unitário de uma classe assim é igualmente simples. Basta instanciar a classe e depois passar o Clock como parâmetro:

Agora vamos criar uma classe injetável (bean) a partir do Clock:

Com isto, temos tudo pronto: o código que receberá a injeção do Clock, o teste unitário e o Clock injetável.

… e abusando

Se você ainda quiser abusar do Clock, você pode aplicar este mesmo conceito para os seus testes de integração, criando cenários inteiros de teste manipulando o tempo, mockando o Clock com @MockBeane alterando o instante dele.

Já implementei vários testes automatizados, executando diversos cenários, usando este recurso. A flexibilidade proporcionada por esta estratégia para criar testes que precisam de dados cadastrados no passado é excelente.

… e abusando²

Agora, se você deseja estressar ao máximo os limites de um teste com Clock, fica a dica: você pode criar um serviço qualquer (Rest, Servlet, você escolhe!), desde que fique disponível apenas em ambiente de desenvolvimento, que possa permitir manipular a data da aplicação da maneira que quiser, bastando passar a data desejada neste serviço disponibilizado. Lembra daqueles testes que seu QA reclamava que eram difíceis de se fazer, pois dependiam de registros passados? Então, não mais :).

Este tipo de funcionalidade basicamente envolve a alteração em tempo de runtime de beans do Spring. Criei um repositório com uma implementação funcional usando um bean Delorean para fazer o meio de campo com o Clock, apenas para ilustrar esta possibilidade. Vocês podem conferir mais detalhes e algumas observações sobre a implementação no próprio repositório.

Bem, é isto. Para testes que uma máquina do tempo viria a calhar, o Clock irá te ajudar.

--

--

Dherik Barison
CWI Software

Java developer, Tech Lead, Stack Overflow enthusiast and contributor: https://dherik.com