Turn back time

Have you ever wished that you were able to go back in time? At least in software development that is relatively easy.

If you ask someone how you could simulate the passing of time for a unit test you might get an answer that involves TypeMock Isolator or something even more wicked. But you can solve that problem with less than a hundred lines of code, once and for all.

In his book Dependency Injection in .NET Mark Seemann introduced a small helper class he calls TimeProvider. It is used as a sample of an Ambient Context and like the DateTime structure it offers some static properties to access the current local time or the current UTC time.

In a post on his blog Seemann shows how descriptive testing with the TimeProvider API can become.

Since I first read about the TimeProvider I used it countless times and it made my life a lot (!!!) easier. I made a few optimizations to reduce the friction of the original code.

public class TimeProvider
{
  private static TimeProvider current;
  static TimeProvider()
  {
    current = new DefaultTimeProvider();
  }
  public static TimeProvider
  {
    get { return current; }
    set
    {
      Guard.AssertNotNull(value, "Current");
      current = value;
    }
  }
  public static DateTime Now
  {
    get { return Current.GetNow(); }
  }
  public static DateTime UtcNow
  {
    get { return Current.GetUtcNow(); }
  }
  protected abstract DateTime GetNow();
  protected abstract DateTime GetUtcNow();
}

This is the default implementation:

public class DefaultTimeProvider : TimeProvider
{
  protected override GetNow()
  {
    return DateTime.Now;
  }
  protected override GetUtcNow()
  {
    return DateTime.UtcNow;
  }
}

And because Moq can’t mock protected methods I wrote an almost as simple implementation for unit testing

public class MockTimeProvider : TimeProvider
{
  private readonly DateTime now;
  private readonly DateTime utcNow;
  public MockTimeProvider(DateTime now)
    : this(now, now)
  {
  }
  public MockTimeProvider(DateTime now, DateTime utcNow)
  {
    this.now = now;
    this.utcNow = utcNow;
  }
  protected override GetNow()
  {
    return this.now;
  }
  protected override GetUtcNow()
  {
    return this.utcNow;
  }
}

I had to change the implementation of the Freeze method from the sample a bit but nothing to worry:

internal static void Freeze(this DateTime dt)
{
    var timeProviderStub = new MockTimeProvider(dt);
    TimeProvider.Current = timeProviderStub;
}

It won’t help you in legacy systems* or when dealing with 3rd party components. But it really helps when testing your own code!

* Unless you replace all calls to DateTime.Now or UtcNow which we did on a project I worked with last year.

Advertisements

Enterprise Library 6.0 – Semantic Logging Application Block CTP

The first bits of EntLib6 are out! Welcome the Semantic Logging Application Block!

It’s based on Event Tracing for Windows (ETW, which is baked into the Windows OS) but additionally offers support for classic logger targets like flat files, databases etc. It provides a structured, extensible log format for all of your log messages which makes processing and searching your log much more convenient.

Read more on the background of semantic logging or directly get some code and start experimenting with the CTP.