C# - how to inject, mock or stub DateTime for unit tests

In this post I will demonstrate how you can stub the DateTime struct in your unit tests. Most commonly the method DateTime.Now or DateTime.UtcNow are used to get the current date and time. Sometimes you make a decision in your code depending on this, which means you want to control this for your tests so you can get better test coverage. You may have some code somewhat like the following in your code base (this is an example from my daily routine):

public class Decision
{
    public string WhatToDo()
    {
        var currentDateTime = DateTime.Now; //The important part
        if (currentDateTime.Hour > 8 && currentDateTime.Hour < 22)
            return Blog();
        else
            return Sleep();
    }

    private string Blog()
    {
        return "Blog!";
    }

    private string Sleep()
    {
        return "Sleep!";
    }
}

In the above the current time decides what to do, between 8 and 22 it is blogging time and outside that it is sleep time. If I want to test what happens in the Sleep() and Blog() method I have to control DateTime.Now to end up on that code path, here I will show some approaches on how to do that. The approaches are:

  • Constructor dependency injection
  • Using a mocking framework
  • Injection through inheritance
  • Using a Func
  • Using a static DateTime

My examples are also applicable to DateTimeOffset. The examples are in C# and I use xUnit for my tests.

Method 1: Constructor dependency injection - the Wrapper class

This is a very common and simple pattern used to control the DateTime.Now struct or any other type that you need to stub. It is often done by wrapping the DateTime in a class like below. First we wrap the DateTime, so that we can provide our own DateTime value or as a default use DateTime.Now in the flow outside our tests:

public class DateTimeWrapper
{
    private DateTime? _dateTime;

    public DateTimeWrapper()
    {
        _dateTime = null;
    }

    public DateTimeWrapper(DateTime fixedDateTime)
    {
        _dateTime = fixedDateTime;
    }

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

We then inject the DateTimeWrapper into the constructor of the Decision class and use that for getting the DateTime:

public class Decision
{
    private readonly DateTimeWrapper _dateTimeWrapper;

    public Decision(DateTimeWrapper dateTimeWrapper)
    {
        _dateTimeWrapper = dateTimeWrapper;
    }

    public string WhatToDo()
    {
        var currentDateTime = _dateTimeWrapper.Now;
        if (currentDateTime.Hour > 8 && currentDateTime.Hour < 22)
            return Blog();
        else
            return Sleep();
    }

    private string Blog()
    {
        return "Blog!";
    }

    private string Sleep()
    {
        return "Sleep!";
    }
}

Our old flow is unbroken as it still just gets a DateTime.Now in the end, but using the above we can now create unit tests where we choose the value used for the DateTime:

[Fact]
public void ShouldBeBlogWhenHourIsTen()
{
    var dateTimeWrapper = new DateTimeWrapper(new DateTime(2020, 01, 01, 10, 00, 00));
    var decision = new Decision(dateTimeWrapper);
    var whatToDo = decision.WhatToDo();
    Assert.Equal("Blog!", whatToDo);
}

[Fact]
public void ShouldBeSleepWhenHourIsTwentyThree()
{
    var dateTimeWrapper = new DateTimeWrapper(new DateTime(2020, 01, 01, 23, 00, 00));
    var decision = new Decision(dateTimeWrapper);
    var whatToDo = decision.WhatToDo();
    Assert.Equal("Sleep!", whatToDo);
}

Above we instantiate the DateTimeWrapper and provide it with a DateTime used for testing. The first test shows that at the time 10 we get the value "Blog!". The second test shows that at the time 23 we get the value "Sleep!".

This approach for controlling the DateTime.Now value is quite verbose, but it has its advantages. It is simple and uses just what is within the framework as no dependencies are required, it is also well known and used.

Method 2: Using a mocking framework

If you write a lot of unit tests you are likely using a mocking framework. In this example I use Nsubstitute to mock an interface that has the responsibility for fetching the current DateTime. It is much like the previous example but less verbose and leverages your mocking framework. First we create an interface and an implementation of it:

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

public class DateTimeWrapper : IDateTimeWrapper {}

In the above we create a simple interface with a "Now" method that returns DateTime.Now. This we need to use for our Decision class and is injected into the constructor:

public class Decision
{
    private readonly IDateTimeWrapper _dateTimeWrapper;

    public Decision(IDateTimeWrapper dateTimeWrapper)
    {
        _dateTimeWrapper = dateTimeWrapper;
    }

    public string WhatToDo()
    {
        var currentDateTime = _dateTimeWrapper.Now;
        if (currentDateTime.Hour > 8 && currentDateTime.Hour < 22)
            return Blog();
        else
            return Sleep();
    }

    private string Blog()
    {
        return "Blog!";
    }

    private string Sleep()
    {
        return "Sleep!";
    }
}

Through our IDateTimerWrapper we are now able to control what DateTime is returned when the Now method is called. We can now substitute what is returned by creating a mock (substitute in NSubstitute) that returns the DateTime we want. We repeat the previous tests using mocking instead:

[Fact]
public void ShouldBeBlogWhenHourIsTen()
{
    var dateTimeWrapper = Substitute.For<IDateTimeWrapper>();
    dateTimeWrapper.Now.Returns(new DateTime(2020, 01, 01, 10, 00, 00));
    var decision = new Decision(dateTimeWrapper);
    var whatToDo = decision.WhatToDo();
    Assert.Equal("Blog!", whatToDo);
}

[Fact]
public void ShouldBeSleepWhenHourIsTwentyThree()
{
    var dateTimeWrapper = Substitute.For<IDateTimeWrapper>();
    dateTimeWrapper.Now.Returns(new DateTime(2020, 01, 01, 23, 00, 00));
    var decision = new Decision(dateTimeWrapper);
    var whatToDo = decision.WhatToDo();
    Assert.Equal("Sleep!", whatToDo);
}

You may find this method to be more elegant than the previous, but it does require for you to use a mocking framework. It also uses fewer lines of code for the wrapper. This is the most common way to control DateTime that I encounter.

Method 3: Injection through inheritance

I got this idea from an answer on this question on stackoverflow, I had never seen or thought about using this approach before.

We start by defining our Decision class again, this time we add the keyword virtual to a GetDateTime() method which returns DateTime.Now. This makes it possible to override this method if we inherit from our Decision class, which we will use to control what GetDateTime() returns:

public class Decision
{
    public string WhatToDo()
    {
        var currentDateTime = GetDateTime();
        if (currentDateTime.Hour > 8 && currentDateTime.Hour < 22)
            return Blog();
        else
            return Sleep();
    }

    protected virtual DateTime GetDateTime()
    {
        return DateTime.Now;
    }

    private string Blog()
    {
        return "Blog!";
    }

    private string Sleep()
    {
        return "Sleep!";
    }
}

In order to test with another DateTime, we need to create a stub (a "test double") as seen below:

public class DecisionTestStub : Decision
{
    private readonly DateTime _dateTime;

    public DecisionTestStub(DateTime dateTime)
    {
        _dateTime = dateTime;
    }

    protected override DateTime GetDateTime()
    {
        return _dateTime;
    }
}

This lets us override what GetDateTime() returns but leaves everything within the class as is, this enables us to have control over the DateTime which can be used for testing purposes. This is demonstrated below where we use our stub with specific DateTime values:

[Fact]
public void ShouldBeBlogWhenHourIsTen()
{
    var decision = new DecisionTestStub(new DateTime(2020, 01, 01, 10, 00, 00));
    var whatToDo = decision.WhatToDo();
    Assert.Equal("Blog!", whatToDo);
}

[Fact]
public void ShouldBeSleepWhenHourIsTwentyThree()
{
    var decision = new DecisionTestStub(new DateTime(2020, 01, 01, 23, 00, 00));
    var whatToDo = decision.WhatToDo();
    Assert.Equal("Sleep!", whatToDo);
}

This approach has some advantages to it: It is not intrusive to the Decision class as it only requires us to use the keyword protected and move how we get our DateTime into another method. There is no need to inject anything into the constructor, so seen from the outside it is untouched. Our stub carries all of the code needed to change the DateTime (the injection in the constructor) for each test. The only disadvantage I can think of, is that we actually do not test our Decision class directly, but an inheritance of it.

Method 4: Using a Func

You can also pass a Func to your constructor or method that will return a DateTime. You can make it have the default value null and if so use DateTime.Now, so you do not interfere with the signature or method or constructor. Below I have added this to the WhatToDo method:

public class Decision
{
    public string WhatToDo(Func<DateTime> getCurrentDateTime = null)
    {
        var currentDateTime = getCurrentDateTime == null ? DateTime.Now : getCurrentDateTime();
        if (currentDateTime.Hour > 8 && currentDateTime.Hour < 22)
            return Blog();
        else
            return Sleep();
    }

    private string Blog()
    {
        return "Blog!";
    }

    private string Sleep()
    {
        return "Sleep!";
    }
}

As mentioned, we use the DateTime provided by the Func, and if the Func is null we use DateTime.Now instead. Below we repeat the same tests as earlier:

[Fact]
public void ShouldBeBlogWhenHourIsTen()
{
    var decision = new Decision();
    var whatToDo = decision.WhatToDo(() => new DateTime(2020, 01, 01, 10, 00, 00));
    Assert.Equal("Blog!", whatToDo);
}

[Fact]
public void ShouldBeSleepWhenHourIsTwentyThree()
{
    var decision = new Decision();
    var whatToDo = decision.WhatToDo(() => new DateTime(2020, 01, 01, 23, 00, 00));
    Assert.Equal("Sleep!", whatToDo);
}

This is quite simple and there is no need for stubs, mocks or anything else. As mentioned the above can be repeated having the constructor take the Func<DateTime> instead of the method.

Method 5: Using a static DateTime

I believe I should mention this approach, but mostly as a warning against it. Even though it is arguably a simple way to achieve this, it also has a major pitfall, you cannot run your tests in parallel. Since this approach relies on a static variable you will run into problems with concurrent calls to it. You could implement some sort of lock but again your tests will block each other and not run in parallel. This reduces performance of your tests, you may see this as less important if your tests run fast.

We first create our DateTimeWrapper class with a static Now property that returns a preset DateTime or DateTime.Now if the preset DateTime is not set (null). We use the method Set() to set the value for the DateTime and Reset() to set it to null. You can see the implementation below:

public class DateTimeWrapper{
    private static DateTime? dateTime;

    public static DateTime Now { get { return dateTime ?? DateTime.Now; } }

    public static void Set(DateTime setDateTime)
    {
        dateTime = setDateTime;
    }

    public static void Reset()
    {
        dateTime = null;
    }
}

Next we use our DateTimeWrapper.Now method in our Decision class in order to get a DateTime:

public class Decision
{
    public string WhatToDo()
    {
        var currentDateTime = DateTimeWrapper.Now;
        if (currentDateTime.Hour > 8 && currentDateTime.Hour < 22)
            return Blog();
        else
            return Sleep();
    }

    private string Blog()
    {
        return "Blog!";
    }

    private string Sleep()
    {
        return "Sleep!";
    }
}

Just as all the previous examples we now start using our new approach on our two test cases:

[Fact]
public void ShouldBeBlogWhenHourIsTen()
{
    var decision = new Decision();
    DateTimeWrapper.Set(new DateTime(2020, 01, 01, 10, 00, 00));
    var whatToDo = decision.WhatToDo();
    Assert.Equal("Blog!", whatToDo);
}

[Fact]
public void ShouldBeSleepWhenHourIsTwentyThree()
{
    var decision = new Decision();
    DateTimeWrapper.Set(new DateTime(2020, 01, 01, 23, 00, 00));
    var whatToDo = decision.WhatToDo();
    Assert.Equal("Sleep!", whatToDo);
}

In the above we set the DateTime we wish to test again on our DateTimeWrapper, which our Decision class then gets using the Now method. This way we can control the DateTime that our Decision class uses.

We use the reset method in our teardown or setup method in our tests. For xUnit that is the constructor of our tests, therefore I have added it here:

public UnitTest() {
    DateTimeWrapper.Reset();
}

If you forget this other tests that rely on DateTime may fail as they get the DateTime from the last run test. This is also why we cannot run tests in parallel.

The biggest advantage of this approach is that it is simple, but you cannot run your tests in parallel, which is a "no go" for most.

That is it

These were my approaches and examples on how you can test code that is depending on the DateTime struct. If you know a smarter or easier way please let me know in the comments down below, I would love to add that to my list. Any other comments are of course also appreciated as well.

If you wish to read some great resources on Test driven development, test doubles or dependency inject, please see the following resources:

Disclosure: Bear in mind that the following links in this post are affiliate links and if you go through them to make a purchase I will earn a commission. Keep in mind that I link these companies and their products because of their quality. The decision is yours, and whether or not you decide to buy something is completely up to you.