Blogtronica

Time based unit testing

Time based unit testing
Photo by Abdul A / Unsplash

How do you test something with time, and you don't want to inject an ITime, resulting in dependencies heavy code?

public string GetGreeting()  
    {
        var response = "Good " + (DateTime.Now.Hour < 12 ? "morning!" : "afternoon!");
        return response;
    }

Simple, use a functional delagate where you can replace the implementation.

public static class DateTimeProvider  
{
    public static Func<DateTime> Now = () => DateTime.Now;
}

public class Worker  
{
    public string GetGreeting()
    {
        var response = "Good " + (DateTimeProvider.Now().Hour < 12 ? "morning!" : "afternoon!");
        return response;
    }
}

And now it is testable!

[Theory]
[InlineData("2060-10-1 00:00:00", "morning")]
[InlineData("2060-10-1 11:59:59", "morning")]
[InlineData("2060-10-1 12:00:00", "afternoon")]
public void TestGreeting(string forDate, string expect)  
{
    DateTimeProvider.Now = () => DateTime.Parse(forDate);
    var sut = new Worker();
    var greeting = sut.GetGreeting();
    Assert.Contains(expect, greeting);
}