2010-06-28 169 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 
    } 
} 
相關問題