Home > C# > How to test DateTime.Now?

How to test DateTime.Now?

This time I want to share with you some kind of testing pattern I got when tried to test some business rules that involves the “today” word.
Imagine that you have a business rule that says “The system should retrieve a list with the not expired products” and “not expired” means “with the ExpirationDate property grater than now”. Usually, this could be implemented like this:

public bool IsExpired 
{
        get 
        { 
                 return ExpirationDate <= DateTime.Now; 
        }
}

Well, if you are using queries (and you should), you will have in some place to put DateTime.Now as a parameter to the query or using a GetDate() like database function.
Suppose then that you need to test it. You create a bunch of products, some expiring before today and some after. But hey! the expiration date is created by some other business rule, something like “The expiration date is three month after the creation date”, and the creation date is, again, using DateTime.Now. How could you control the current date?

Let me introduce to you the class SystemDate:

public static class SystemDate
{
	private static IDateProvider provider;

	public static void Use(IDateProvider dateProvider)
	{
		provider = dateProvider;
	}
	static SystemDate()
	{
		UseDefault();
	}
	public static DateTime Today
	{
		get
		{
			return provider.Today;
		}
	}
	public static DateTime Now
	{
		get
		{
			return provider.Now;
		}
	}

	public static void UseDefault()
	{
		provider = new DateTimeProvider();
	}
}

public interface IDateProvider
{
	DateTime Today { get; }
	DateTime Now { get; }
}

public class DateTimeProvider : IDateProvider
{
	public DateTime Today
	{
		get { return DateTime.Today; }
	}

	public DateTime Now
	{
		get { return DateTime.Now; }
	}
}

Instead of use DateTime.Now, you could use SystemDate.Now. The benefit of that is that you can change the date provider for a Mock one. So, let me introduce to you the time machine:

public class DeLorean : IDateProvider
{
	private DeLorean()
	{
	}

	public static DeLorean StoppedIn(DateTime moment)
	{
		return new DeLorean
				   {
					   Now = moment
				   };
	}

	public DateTime Today
	{
		get { return Now.Date; }
	}

	public DateTime Now { get; private set; }

	public void TravelTo(DateTime time)
	{
		Now = time;
	}
}

The usage is pretty simple:

var timeMachine = DeLorean.StoppedIn( new DateTime(2010, 1, 1) );
products.Add( new Product() );
timeMachine.TravelTo( new DateTime( 2010, 1, 5 ) );
products.Add( new Product() );
timeMachine.TravelTo ( new DateTime(2010, 4, 1) );
Assert.That( products.NotExpired, Have.Count(1) );

Edit: you can download the source code from http://ivowiblo.googlecode.com/svn/SystemDate/

Categories: C# Tags: ,
  1. Lenny
    February 1, 2010 at 8:51 pm

    Sounds familiar to me! That was a good tdd approach.
    Miss those crazy class names!

  2. Leandro
    February 1, 2010 at 10:00 pm

    Excellent!, you used the flux capacitor successfully.

  1. No trackbacks yet.

Leave a comment