为什么不直接使用DateTime.Now?

Syn*_*ror 1 c# interface

我最近一直在努力学习接口.

我看到了这段代码,无法解决为什么你不能单独使用DateTime.Now它.我不确定为什么界面很有用,有人可以解释一下吗?本书的作者试图解释,但我真的不明白如何按照他们的说法实现它:

程序员是否在抽象的海洋中迷失了自己?你可能会想到这么想,但实际上这很聪明.想象一下,你必须在一个类上运行一些测试,根据当前时间(或日期)给出不同的结果.这根本不常见; 也许这是一个需要在给定日期获得汇率的金融应用程序.因此,如果代码库直接在方法中使用DateTime.Now,请尝试测试.使用INowResolver,您可以现在注入并测试昨天,现在和明天

public interface INowResolver { DateTime GetNow(); } 

public class NowResolver : INowResolver { 
   public DateTime GetNow() {  
       return DateTime.Now;     
   } 
}
Run Code Online (Sandbox Code Playgroud)

当我测试它时,如果我使用该NowResolver.GetNow方法或刚刚使用,结果是相同的DateTime.Now.

测试:

        NowResolver now = new NowResolver();
        Console.WriteLine(now.GetNow());
        Console.WriteLine(DateTime.Now);
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine(now.GetNow());
        Console.WriteLine(DateTime.Now);
Run Code Online (Sandbox Code Playgroud)

输出:

07/02/2019 15:14:56
07/02/2019 15:14:56
07/02/2019 15:14:57
07/02/2019 15:14:57
Run Code Online (Sandbox Code Playgroud)

Nei*_*eil 9

在编写单元测试时,每次运行测试时,以完全相同的方式执行测试非常重要.

如果您的测试(或正在测试的代码)使用DateTime.Now(或DateTime.UtcNow),那么每次运行时您将获得不同的测试结果(假设您正在测试包含所述测试的属性DateTime).

如果你抽象DateTime出一个接口,你就可以这样做,这样当你的测试运行时,它总是在INowResolver.Now调用时返回相同的时间.

示例: 在此测试中,时间将始终为2018年1月1日.

public class MyTest
{
    public class TestNow : INowResolver
    {
       public DateTime Now {get;set;}
       public DateTime GetNow() => Now;
    }

    [Test]
    public void MyTest()
    {
       var resolver = new TestNow { Now = new DateTime(2018,1,1) }

       var testClass = new TestClass(resolver);

    }
}
Run Code Online (Sandbox Code Playgroud)

实际上,如果我使用过这种方法的所有情况都Now属于一个属性,就像它所在的那样DateTime.Now,而不是一个函数.