我最近一直在尝试了解界面。
我看到了这段代码,无法理解为什么您不单单使用DateTime.Now
的原因。我不确定界面为什么有用,有人可以解释一下吗?这本书的作者试图解释,但是我真的不明白如何以他们所说的方式实现它:
程序员是否在抽象的海洋中迷失了自己?你可能是 倾向于这样想,但实际上这很聪明。想像你 必须在提供不同结果的类上运行一些测试 取决于当前时间(或日期)。这一点并不罕见; 也许这是一个需要获取汇率的金融应用程序 在给定的日期。因此,请尝试测试代码库是否具有DateTime.Now 直接在方法中。使用INowResolver,您可以立即注入 并测试昨天,现在和明天
public interface INowResolver { DateTime GetNow(); }
public class NowResolver : INowResolver {
public DateTime GetNow() {
return DateTime.Now;
}
}
当我测试它时,如果我使用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);
输出:
07/02/2019 15:14:56
07/02/2019 15:14:56
07/02/2019 15:14:57
07/02/2019 15:14:57
答案 0 :(得分:8)
编写单元测试时,每次运行测试时都必须以完全相同的方式执行测试,这一点很重要。
如果您的测试(或正在测试的代码)使用DateTime.Now
(或DateTime.UtcNow
),则每次运行时,您都会得到不同的测试结果(假设您正在测试包含上述{ {1}}。
如果您将DateTime
提取到一个接口中,则可以使其变得如此,以便在运行测试时,它总是在调用DateTime
的同一时间返回。
示例:在此测试中,时间始终为2018年1月1日。
INowResolver.Now
实际上,如果在所有情况下我都使用此方法,则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);
}
}
是属性,就像Now
中的属性一样,而不是函数。
答案 1 :(得分:4)
正如书中所指出的,这里的重点是测试。
让我们说您有逻辑,需要在星期六做一些特别的事情。您想为此编写一个测试(很自然)。直接使用DateTime.Now
只能在星期六上运行测试。使用该界面,您可以拥有一个总是返回日期为星期六的日期的模拟,因此可以随时运行测试。
答案 2 :(得分:1)
补充上面的答案,它可以用来冻结时间:
<块引用>在网络请求中,您希望冻结时间,以便您修改的所有内容 日期对齐(即不是+/-几秒钟
意思是,您可以实现 IDisposable
覆盖,以便可以在这样的固定范围内操作时间。
using (var o = new OverrideDateTimeProvider(DateTimeProvider.Now))
{
// logic
entity.Created = o.UtcNow;
// other logic that can takes several seconds
var otherEntity = CreateAsync();
otherEntity.Created = o.UtcNow;
// persistance logic
uow.Commit();
}
有关详细信息,请参阅 this repository。
答案 3 :(得分:0)
Private Sub StandRev()
Dim VlookUp As Range
Dim lastrev As Date
With Worksheets("Tables") 'sets a look up range within the table "Contact"
Set VlookUp = Contact.Parent.Range(Contact.ListColumns("SID").DataBodyRange, Contact.ListColumns("Last Review").DataBodyRange)
lastrev = Application.WorksheetFunction.VlookUp(RevSID, VlookUp, 8,False) '*** problem here -- RevSID variable is assigned in previous sub
' no data is saved in variable, program ends sub
If lastrev > AttempDate2 Then
'code that will replace lastrev with data in AttempDate2, AttempDate2 varaiable assigned in another sub
End If
End With
End Sub
实现将使用NowResolver
。另一个实现可能有DateTime.Now
返回的是上个星期六或昨天等。
该接口保证每个版本,每个实现将提供一个GetNow
方法。类本身决定GetNow
对其的含义。