Testing DateTime.Now
When you are doing Test Driven Development (TDD) many time during the testing phase you’ll find yourself with a code that depends on current time.
It’s not possible write tests for this code as DateTime.Now changes constantly.
Let’s take a look at following method:
public string CreateName(...) { return "name " + DateTime.Now; }
The solution to this problem is simple. We’ll introduce Clock class with the same interface as DateTime:
public string CreateName(...) { return "name " + Clock.Now; }
We’d like the test to look something like this:
[Test] public void CreateName_AddsCurrentTimeAtEnd() { using (Clock.NowIs(new DateTime(2010, 12, 31, 23, 59, 00))) { string name = new ReportNameService().CreateName(...); Assert.AreEqual("name 2010-12-31 23:59:00", name); } }
Tests should not leave any side effects. This is why we are using IDisposable pattern. After text execution Clock.Now is reverted and again returns current time.
Finally this is how Clock class looks like:
public class Clock : IDisposable { private static DateTime? _nowForTest; public static DateTime Now { get { return _nowForTest ?? DateTime.Now; } } public static IDisposable NowIs(DateTime dateTime) { _nowForTest = dateTime; return new Clock(); } public void Dispose() { _nowForTest = null; } };
February 1st, 2014 at 17:03
It is easier to use Moles (http://research.microsoft.com/en-us/projects/moles/) from MS RiS, which are part of Pex (http://research.microsoft.com/en-us/projects/pex/)
February 2nd, 2014 at 06:36
1. You need to have Pex installed.
2. Is it simple to revert Mole to the original behavior?
3. Does it happen automatically?
February 2nd, 2014 at 07:16
Moles can intercept static methods like DateTime.Now (like TypeMock Isolator), but you’re better off abstracting it so you don’t have to rely on those tools. It will just make your code more robust if you can design it without those tools.
This is a fine example and there are others too that all you to work with DateTime without relying on the static Now property.