The journeylism of @yreynhout

On CQRS, DDD(D), ES, …

How do you control time?

Granted, in some systems this might not be an issue. But if you want to be able to test your system’s behavior in a deterministic fashion, it becomes important to be able to control time.

So how do you control time in your code? Simple, you define your own Clock and use it instead of the System.DateTime static members.

public static class Clock {
  static Func<DateTime> _nowValueProvider;

  static Clock() { _nowValueProvider = () => DateTime.Now; }

  public static void Initialize(Func<DateTime> nowValueProvider) {
    _nowValueProvider = nowValueProvider;
  }

  public static DateTime Now { get { return _nowValueProvider(); } }
  public static DateTime Today { get { return Now.Date; } }
}

Now, I’m not gonna take credit for this code. It was authored by my coworker Wouter Naessens and inspired by an old Ayende post (http://ayende.com/blog/3408/dealing-with-time-in-tests). People using NodaTime will call this a cheap rip-off (http://code.google.com/p/noda-time/source/browse/src/NodaTime/Clock.cs). If you search the net, you’ll find other similar examples. Regardless of how you decide to implement this, what’s important is that you do.

Those that have a copy of NDepend can scan their code for usages of DateTime.Now, DateTime.Today, … and fail the build if any of those are detected.

Now imagine you’re using messaging and you want to test your system in a deterministic way. Setting that clock in unit tests is all fine and dandy, but what about rolling time forward (or backward if need be) between two consecutive commands sent to your system? Simple, you define a system command called SetClock.

public class SetClock : IMessage {
  public DateTime Now { get; private set; }
  public SetClock(DateTime now) {
    Now = now;
  }
}

public class SetClockHandler : IHandle<SetClock> {
  public void Handle(SetClock message) {
    Clock.Initialize(() => message.Now);
    //If you want to keep time rolling forward
    //from message.Now onwards you'll have to be
    //more inventive.
  }
}

You could also embed the clock’s time as a header in the command’s envelope, allowing a message handler to initialize the clock off the header value. There are lots of variations possible.

Using this technique you should be able to replay use cases that involve time, or do acceptance/integration testing that involves time.

Advertisements

2 responses to “How do you control time?

  1. heischo December 7, 2011 at 16:57

    “return Now.Today;” in Line11 throws “Member ‘System.DateTime.Today.get’ cannot be accessed with an instance reference; qualify it with a type name instead”

    I advise “return Now.Date;” instead 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: