How to mock DateTime in unit tests

Cosmin Vladutu
2 min readOct 21, 2021

--

To use DateTime.Now, DateTime.Today and so on in your code, it’s a terrible idea, everyone knows that, but still there is legacy code that is hard to be re-written, or the business doesn’t give you the time to clean “this little thing”. (You can avoid the DateTime issues from your unit tests using a wrapper around it and an interface that gives you “Now” and so on, but how to avoid the problem isn’t the purpose of the article, how to be able to “tackle” it, it is!). I used shims and Pose as a “helper” to do this. It is pretty nice and easy to use, you can create shims for statics, of course, it has some bugs, but the “toy” is still maintained.

Now let’s see how our code looked like and how did it help me:

One (unnecessary) interface:

public interface IMyLogic{    DateTime GetDateFromFuture(int noOfDays);}

The implementation of the interface (Our logic)

public class MyLogic : IMyLogic{public DateTime Today { get; } = DateTime.Today;public DateTime GetDateFromFuture(int noOfDays){return Today.AddDays(noOfDays);}}

And this is how our test looks like:

[Fact]public void When_GetDateFromFutureIsCalledWith5AsParamAndMockedCurrentDate_Expect_CorrectResult(){//ArrangeIMyLogic logic = null;Shim shim = Shim.Replace(() => DateTime.Today).With(() => new DateTime(2019, 07, 20));PoseContext.Isolate(() =>{logic = new MyLogic();}, shim);//Actvar result = logic.GetDateFromFuture(5);//AssertAssert.Equal(new DateTime(2019, 07, 25), result);}

What I like about Pose is that I can replace static methods and non-virtual with delegates and compare with Microsoft Fakes all the magic is done in memory, so no “pollution” with re-written assemblies is done, nor any “fake system interaction”.

A second solution which is far from mocking and getting what you want, but does the job, would be to use “fluent assertions”.

var modified = DateTime.UtcNow;
modified.Should().BeCloseTo(DateTime.UtcNow, 1.Minutes());

In the example from above, you have the modified variable as UtcNow. In the Fluent Assertions NuGet, you’ll have “BeCloseTo” which will help you to make your tests green. It’s not the same as using Pose, but you can configure it pretty decent to get your job done fast. If you want more robust tests I would still go with making a “fake” DateTime.Now/UtcNow.

--

--

Cosmin Vladutu
Cosmin Vladutu

Written by Cosmin Vladutu

Software Engineer | Azure & .NET Full Stack Developer | Leader

No responses yet