Muitas pessoas me perguntam como escrever testes de unidade de classes que lidam com datas. E, geralmente o problema está em como testar classes que usam a data/hora atual.

Esse problema acontece pois grande parte das APIs que lidam com datas, tanto no mundo .Net quanto no mundo Java, fazem uso de métodos estáticos. Por exemplo:

DateTime.Now // C#
Calendar.getInstance() // Java

Generalizando o problema, a dificuldade nao é testar datas, mas sim qualquer classe que faz uso de métodos estáticos. Por exemplo, como escrever um teste para o método abaixo?

public int DiasEntreHjEAData(DateTime data) {
  return (DateTime.Now - data).TotalDays;
}

A propriedade Now sempre irá devolver a data corrente, dificultando assim a escrita do teste; como escrever um teste onde o cenário muda o tempo todo?

Não conseguir simular o comportamento do método Now, e esse eh um dos problemas de usar métodos estáticos: dificulta o teste das classes que os utilizam (além de não permitir o uso decente de polimorfismo, mas isso é uma outra discussão…)

Para resolver esse problema, precisamos deixar de usar métodos estáticos. Mas e como fazer com as APIs que já existem, e não podemos mudá-las, como é o caso da API de DateTime?

Isso não nos impede de criarmos uma abstração em cima disso! Veja o código abaixo:

public interface Relogio {
  DateTime Hoje();
}

public class RelogioDoSistema : Relogio {
  public DateTime Hoje() {
    return DateTime.Now;
  }
}

Veja que criamos a interface Relogio, que abstrai o problema de calcular a hora atual. Nosso método acima agora, em vez de invocar o método estático, faz uso da nova abstração:

public class Algoritmo {

  // recebido pelo construtor
  private Relogio relogio;

  public int DiasEntreHjEAData(DateTime data) {
    return (relogio.Hoje() - data).TotalDays;
  }
}

Pronto. Veja agora que testar essa classe é facil. Basta passarmos um mock e simular o comportamento esperado do Relogio.

Resumindo, métodos estáticos dificultam a escrita de testes de unidade. Para resolver isso podemos: evitar a escrita de métodos estáticos, ou criar abstrações que escondem esses métodos. Nao é feio criar abstrações como a Relogio; feio é não testar! 🙂