What's a good way to overwrite DateTime.Now during testing?

Craig.Nicol picture Craig.Nicol · Sep 4, 2008 · Viewed 38k times · Source

I've got some (C#) code that relies on today's date to correctly calculate things in the future. If I use today's date in the testing, I have to repeat the calculation in the test, which doesn't feel right. What's the best way to set the date to a known value within the test so that I can test that the result is a known value?

Answer

Blair Conrad picture Blair Conrad · Sep 4, 2008

My preference is to have classes that use time actually rely on an interface, such as

interface IClock
{
    DateTime Now { get; } 
}

With a concrete implementation

class SystemClock: IClock
{
     DateTime Now { get { return DateTime.Now; } }
}

Then if you want, you can provide any other kind of clock you want for testing, such as

class StaticClock: IClock
{
     DateTime Now { get { return new DateTime(2008, 09, 3, 9, 6, 13); } }
}

There may be some overhead in providing the clock to the class that relies on it, but that could be handled by any number of dependency injection solutions (using an Inversion of Control container, plain old constructor/setter injection, or even a Static Gateway Pattern).

Other mechanisms of delivering an object or method that provides desired times also work, but I think the key thing is to avoid resetting the system clock, as that's just going to introduce pain on other levels.

Also, using DateTime.Now and including it in your calculations doesn't just not feel right - it robs you of the ability to test particular times, for example if you discover a bug that only happens near a midnight boundary, or on Tuesdays. Using the current time won't allow you to test those scenarios. Or at least not whenever you want.