Running into Problems Testing with DateTime.Now()? Here’s the Fix

As a developer, there’s a strong chance you’ve come across DateTime objects and have probably used DateTime.Now()to get the current date and time. On my current project, I recently ran into an issue when trying to test a portion of code that calls DateTime.Now(). I’ll provide some background on the issue and the steps I took to overcome this problem.

Background

As part of my current project, my team was tasked with designing and building out an API. One of the POST endpoints we needed to create had to make a call to a REST API that already existed within the client’s repository. I had to include a date in the request body sent to the REST API The date was a required parameter and didn’t matter too much for our purposes so my first instinct was to create a variable ‘date’ and use DateTime.Now().

The Problem with DateTime.Now()

As you may have guessed, I ran into some issues when trying to unit-test this code. In the unit test, I set up a MockRestApiClient using the Moq library and then made a call to the service function. The result of the service function call was coming back as null: System.NullReferenceException: Object reference not set to an instance of an object. The service call to the REST API was returning a 500.

This was difficult to debug at first because we were using the Refit library to consume the REST API. Refit provides a way to use abstraction to make API calls. This meant that I could not easily debug the REST API endpoint without cloning the project and attempting to get it running locally. This was a messy and in-depth process so this was a last resort.

The Culprit

After many, many breakpoints, I finally found the culprit. The date-time used in the request body was off by a mere milliseconds from the date-time that the request was being tested against. So here is what I learned in my search for a solution to testing C# code that uses the DateTime.Now() function.

The Solution

In my search for a solution, it seemed to me DateTime.Now() should probably not be used directly in business logic. Instead, we could use dependency injection to pass the current date and time as a parameter to any classes or methods that may need them. This approach would also allow us to use a fixed date when testing. To implement this, I created a DateTimeProvider service. This service would expose the DateTime.Now() method and return the current date and time.

public class DateTimeProviderService : IDateTimeProviderService
{
   public virtual DateTime Now { get; } = DateTime.Now;
}

The next step would be mocking out the DateTimeProvider service for unit testing. In our project, we use Moq, a popular mocking library, to create mock objects and set up certain behaviors for testing. Moq simulates the behavior of dependencies (like services) without using the actual implementation. Then, I created a variable with a specific date and set up the MockDateTimeProvider to return that variable. This also allows me to test different scenarios as well, such as past, present, and future dates.

protected readonly Mock<IDateTimeProviderService> MockDateTimeProviderService = new();

var date = new DateTime(2023, 6, 12);

MockDateTimeProviderService.Setup(x => x.Now)
.Returns(date);

That was our fix. What approaches have you taken when testing code that uses DateTime.Now()?

Conversation

Join the conversation

Your email address will not be published. Required fields are marked *