2010-06-28 163 views
6

目前我正在编写一个组件的单元测试,该组件测试日期时间特定。我创建了IDateTimeProvider接口,它可以直接作为DateTime.UtcNow包装和业务对象使用接口而不是DateTime。看起来DateTime有点超载,应该分成一个值和一个从操作系统获取该值的东西。我想知道是否有一个特定的原因,不在.NET中有一个接口(IDateTimeProvider)(IClock)?为什么在.NET中没有IDateTimeProvider并且DateTime具有Now getter?

回答

7

简而言之:因为BCL的大部分并不是为可测性设计的。

在“核心”功能方面,对于随机数生成也是如此 - 许多与HTTP相关的类更难以伪造:(至少在这种情况下,可以很容易地引入你自己的。时钟接口

从有利的一面,当Noda Time是可供生产使用,它不仅能提供更好的日期/时间API比BCL - 它会提供更多的测试友好的:)

+0

不要忘记,System.IO ... – 2011-11-28 16:02:11

1

我们始终如一地使用DateTimeProvider包装类,如果需要,我们可以在测试上下文中重写该类包装类...

0

http://learn.typemock.com/typemock-isolator/能够模拟DateTime(和其他mscorlib类型)所以DateTime.Now不再是问题。但缺点是,这可能会导致开发人员设计更糟糕的东西,因为嘲笑DateTime.Now!没有问题!

也许使用类似IDateTimeProvider的东西是更好的解决方案。

但是,如果您使用的是第三方库, DateTime TypeMock-Isolatior可能是一个解决方案/解决方法。

而且微软研究院的摩尔/支脚是凉的东西:http://channel9.msdn.com/blogs/peli/moles-replace-any-net-method-with-a-delegate(展示了如何用一个委托更换任何.NET方法/属性 - 例如DateTime.Now ;-))

+0

不良链接?无法打开页面。 – Kimi 2011-11-28 10:23:18

0

我张贴了这个答案,另一个问题,但如果您正在寻找测试DateTime.Now的简单方法,它也适用于此。

我喜欢做的是创建一个公共函数,它返回需要当前日期/时间的类中的DateTime(Func<DateTime>),并将其设置为默认返回DateTime.Now。然后,在测试期间,我用一个测试函数覆盖它,该函数返回我想测试的任何DateTime。

public class MyClass 
{ 
    public Func<DateTime> 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 
    } 
} 
相关问题