如何测试依赖于当前日期的逻辑

Roh*_*wal 8 c# unit-testing

我有这种方法取决于当前日期.它检查今天是太阳,周一,周二还是周三,然后它给出了5天的交货时间.如果它是星期四,星期五或星期六那么它给出了6天的交货时间来解释周末.

private DateTime GetEstimatedArrivalDate()
{
    DateTime estimatedDate; 
    if (DateTime.Now.DayOfWeek >= DayOfWeek.Thursday)
    {
        estimatedDate = DateTime.Now.Date.AddDays(6);
    }
    else
    {
        estimatedDate = DateTime.Now.Date.AddDays(5);
    }
    return estimatedDate; 
}
Run Code Online (Sandbox Code Playgroud)

实际的估算逻辑更复杂.为了这个问题,我简化了它.我的问题是如何根据今天的日期为这样的事情编写单元测试?

Mar*_*ers 19

您需要将当前日期作为参数传递:

private DateTime GetEstimatedArrivalDate(DateTime currentDate)
{
    DateTime estimatedDate; 
    if (currentDate.DayOfWeek >= DayOfWeek.Thursday)
    {
        estimatedDate = currentDate.AddDays(6);
    }
    else
    {
        estimatedDate = currentDate.AddDays(5);
    }
    return estimatedDate; 
}
Run Code Online (Sandbox Code Playgroud)

在实际代码中,您可以这样称呼它:

DateTime estimatedDate = GetEstimatedArrivalDate(DateTime.Now.Date);
Run Code Online (Sandbox Code Playgroud)

然后你可以测试它如下:

DateTime actual = GetEstimatedArrivalDate(new DateTime(2010, 2, 10));
DateTime expected = ...;
// etc...
Run Code Online (Sandbox Code Playgroud)

请注意,这也修复了程序中潜在的错误,其中日期在连续调用之间发生变化DateTime.Now.


Eri*_*bes 10

一般来说,您需要抽象获取接口背后的当前日期和时间的方法,例如:

public interface IDateTimeProvider
{
    DateTime Now { get; }
}
Run Code Online (Sandbox Code Playgroud)

真正的服务是:

public class DateTimeProvider: IDateTimeProvider
{
    public DateTime Now
    {
        get
        {
            return DateTime.Now;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

测试服务将是:

public class TestDateTimeProvider: IDateTimeProvider
{
    private DateTime timeToProvide;
    public TestDateTimeProvider(DateTime timeToProvide)
    {
        this.timeToProvide = timeToProvide;
    }

    public DateTime Now
    {
        get
        {
            return timeToProvide;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对于需要当前时间的服务,让他们将IDateTimeProvider作为依赖项.对于真实的东西,传递一个新的DateTimeProvider(); 当你是一个组件时,传入一个新的TestDateTimeProvider(timeToTestFor).