The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Testability Of Date-Dependent Code

Posted by Davy Brion on October 21st, 2009

Just read a post by Jonathan Oliver where he talks about a solution he saw to tackle the problem of date-dependent code in tests. As you probably know, code that uses the current date can very easily cause testability problems. Code that accesses DateTime.Now or DateTime.UctNow can quite easily cause tests to fail for no valid reason when the tests happen to run on a certain date, on weekend days, at the end of the month, etc…

The problem obviously is that you can’t override the value that DateTime.Now will return during your tests. Many people seem to resort to using some kind of DateTimeService dependency which each piece of code that needs the current date will use. Basically, something like this:

    public interface IDateTimeService

    {

        DateTime Now { get; }

    }

The implementation that will be used at runtime then looks like this:

    public class DateTimeService : IDateTimeService

    {

        public DateTime Now

        {

            get { return DateTime.Now; }

        }

    }

Code that needs the current date simply declares a dependency on IDateTimeService and at run-time the IOC container will inject an instance of DateTimeService to fulfill the IDateTimeService dependency. At test-time, the IDateTimeService is mocked so you can easily set which date should be returned for each test.

Personally, i’m not a fan of this approach. I mean, i use the same approach for most dependencies but for simply getting the current date this is a bit too much IMO.

Instead, we simply use something like this:

    public static class DateTimeProvider

    {

        private static DateTime? dateTimeToReturn;

 

        public static DateTime Now

        {

            get { return dateTimeToReturn == null ? DateTime.Now : dateTimeToReturn.Value; }

        }

 

        public static void SetDateTimeToReturn(DateTime overriddenCurrentDateTime)

        {

            dateTimeToReturn = overriddenCurrentDateTime;

        }

 

        public static void ResetCurrentDateTime()

        {

            dateTimeToReturn = null;

        }

    }

And our real code simply calls DateTimeProvider.Now instead of DateTime.Now. In our tests, we call the SetDateTimeToReturn method to provide the date that we want to use for a particular test. At the end of the test, simply call the ResetCurrentDateTime method and that’s it.

I generally don’t like static methods but in this case, this is a very simple solution to this specific problem. And you know how the saying goes: “do the simplest thing that could possibly work”. And as long as that works, resist the urge to change it.

15 Responses to “Testability Of Date-Dependent Code”

  1. Andrey Titov Says:

    I’ve seen a code that relies on two subsequent DateTime.Now calls returns the same value. I don’t remember how it exactly looks, but it was something like this:
    if(IsPaidHour(DateTime.Now))
    {
    price = GetCurrentPrice();
    }
    else
    {
    price = 0;
    }

    and GetCurrentPrice() also calls DateTime.Now and throws if called in a wrong time. ;-)

    So since that I count calls to DateTimeService.

  2. Reflective Perspective - Chris Alcock » The Morning Brew #459 Says:

    [...] Testability Of Date-Dependent Code – Davy Brion talks about two common techniques to enable the reliable testing of Date based code either by providing the date obtaining routine with a service which can be overridden for testing, or by routing all calls for dates through a custom static method which can be provided with dates to return [...]

  3. Karsten Says:

    Ayende uses a variation of the same technique: http://ayende.com/Blog/archive/2008/07/07/Dealing-with-time-in-tests.aspx

  4. Stefano Ricciardi Says:

    This looks like a nice trick. Have you noticed any run-time penalties due to this level of indirection?

    I am considering scenarios like bulking thousands (if not millions) of records where the the current time is used as a part of the key.

  5. Davy Brion Says:

    the performance cost that comes with this level of indirection will definitely not be noticable. Even if you’ve got iterations of millions, you won’t notice this compared to _other_ performance penalties that you most likely will notice when dealing with that kind of volume.

    or put differently: if you’re dealing with millions of records and you notice a difference because of this trick, then i will very gladly tip my hat to you sir :)

  6. Mike Says:

    I posted about this topic a while back http://journalofasoftwaredev.wordpress.com/2009/01/31/obstacles-of-unit-testing-methods-to-side-step-them-part-1-date-and-time/ using this technique it also mentions the Ayende method Karsten has linked to above. Once I get some time I should finish the rest of series off!

  7. Urs Enzler Says:

    Furthermore, I would suggest to not use a singleton but pass the service to its client with dependency injection.

  8. Davy Brion Says:

    @Urs

    did you read the first part of the post? :P

  9. KG2V Says:

    For years, I’ve just gone the other way – Datetime is a passed parameter

  10. Shawn Neal Says:

    A DateTime service is overkill for most scenarios. We do EXACTLY what you’re doing with your DateTimeProvider, works like a champ. I’m just waiting for someone to write a test that forgets to reset the time provider, but that hasn’t happened yet.

  11. Mel Grubb Says:

    Here’s a third variation for you using a nestable, thread-local-storage-based “context” class.
    http://melgrubb.spaces.live.com/blog/cns!A44BB98A805C8996!263.entry

    The implementation may be more “overkill”, but it makes the usage nice and simple.

  12. Jonathan Oliver Says:

    One point I’d like to mention is that of using IDisposable to ensure that the correct/real DateTime is restored at the end of your operational context. Since posting my original article, I have create written another one introducing some open source code to address this very issue:
    http://jonathan-oliver.blogspot.com/2009/10/testing-timestatic-calls-and.html

    It’s very similar to Mel Grubb’s approach (which I have become aware of because of his comment above), the difference being that my approach stores the DateTime object on the thread-local store rather than DateTimeContext.

  13. SeeR Says:

    This is what I’m using


    public class SomeClass
    {
    public static Func Now = () => DateTime.Now;

    public void SomeMethod()
    {
    ...
    var x = Now().Hour;
    ...
    }
    }

    And than I just setup SomeClass.Now in each of my tests

  14. Eric Smith Says:

    Great idea – just one problem—you can’t run multiple tests simultaneous in separate threads. How about a [ThreadStatic] dateTimeToReturn?

  15. Davy Brion Says:

    @Eric

    we don’t run multiple tests simultaneously so it works… and like i said “And as long as that works, resist the urge to change it.”

    once it stops working (like when switching to a multi threaded testrun) then you obviously change it :)

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>