为什么.NET中没有IDateTimeProvider而DateTime现在有getter?
目前我正在为一个进行日期时间特定validation的组件编写unit testing。 我创建了IDateTimeProvider
接口,它充当DateTime.UtcNow
包装器,业务对象直接使用接口而不是DateTime
。 看起来DateTime有点过载,应该分成一个值和一个从操作系统中获取该值的东西。 我想知道在.NET中是否有特殊原因没有IDateTimeProvider
( IClock
)接口?
简单地说:因为BCL的大部分不是为可测试性而设计的。
就“核心”function而言,随机数生成也是如此 – 并且许多与HTTP相关的类更糟糕的假装:(至少在这种情况下,引入自己的时钟接口相当容易。
从好的方面来说,当Noda Time准备好用于生产时,它不仅会提供比BCL更好的日期/时间API – 它将提供更加测试友好的:)
我们一直使用DateTimeProvider包装器类,如果需要,我们可以在测试环境中覆盖它…
http://learn.typemock.com/typemock-isolator/能够模拟DateTime( 以及其他mscorlib类型 ),因此DateTime.Now不再是问题。 但缺点当然是这可能导致开发人员设计他们的东西更加糟糕,因为模拟DateTime没有问题。现在!
也许使用像IDateTimeProvider这样的东西是更好的解决方案。
但是如果你正在使用第三方lib继电器,例如DateTime TypeMock-Isolatior可能是一个解决方案/解决方法。
微软研究院的Moles / Stub也很酷: http : //channel9.msdn.com/blogs/peli/moles-replace-any-net-method-with-a-delegate (演示了如何替换任何.NET方法/属性)与代表 – 例如DateTime.Now ;-))
我将此答案发布到另一个问题,但如果您正在寻找一种测试DateTime.Now
的简单方法,它也适用于此。
我喜欢做的是创建一个公共函数,该函数在需要当前日期/时间的类中返回DateTime( Func
),并将其设置为默认返回DateTime.Now。 然后,在测试期间,我使用测试函数覆盖它,该函数返回我想要测试的任何DateTime。
public class MyClass { public Func DateTimeNow = () => DateTime.Now; public void MyMethod() { var currentTime = DateTimeNow(); //... do work } } public class MyClassTest { public void TestMyMethod() { // Arrange var myClass = new MyClass(); myClass.DateTimeNow = () => new DateTime(1999, 12, 31, 23, 59, 59); // Act myClass.MyMethod(); // Assert // my asserts } }