Dealing with time in tests

time to read 1 min | 167 words

One of the more annoying things to test is time sensitive code.

I just spent five minutes trying to figure out why this code if failing:

repository.ResetFailures(failedMsgs);
var msgs = repository.GetAllReadyMessages();
Assert.AreEqual(2, msgs.Length);

Reset failures will set the retry time of the failed messages to 2 seconds in the features. GetAllReadyMessages will only get messages that are ready now.

Trying to test that can be a real pain. One solution that I have adopted across all my projects is introducing a separate concept of time:

public static class SystemTime
{
	public static Func<DateTime> Now = () => DateTime.Now;
}

Now, instead of calling DateTime.Now, I make the call to SystemTime.Now(), and get the same thing. This means that I can now test the code above easily, using:

SystemTime.Now = () => new DateTime(2000,1,1);
repository.ResetFailures(failedMsgs); 
SystemTime.Now = () => new DateTime(2000,1,2);
var msgs = repository.GetAllReadyMessages(); 
Assert.AreEqual(2, msgs.Length);

This is a really painless way to deal with this issue.