2010-03-20 46 views
5

我使用VS2008的目標.NET 2.0框架,以防萬一,我不能改變這一點:)單元測試目的如何改變「今天的日期」?

我有一個DateCalculator類。其方法GetNextExpirationDate嘗試確定下一個到期日,內部使用DateTime.Today作爲基準日期。

當我寫單元測試時,我意識到,我想測試GetNextExpirationDate不同的「今天」的日期。

這樣做的最好方法是什麼?以下是我考慮過的一些替代方案:

  • 公開一個屬性/重載方法,參數爲baselineDate,僅在單元測試中使用它。在實際客戶端代碼中,忽略屬性/重載方法而偏向於默認爲baselineDateDateTime.Today的方法。我不願意這樣做,因爲它使DateCalculator類的公共接口很尷尬。
  • 創建一個名爲baselineDate保護字段在內部設置爲DateTime.Today。測試時,從DateCalculator派生DateCalculatorForTesting,通過構造方法設置baslineDate。它保持公共接口清潔,但仍然不是很好 - baselineDate已被保護,並且需要派生類,兩者都僅用於測試。
  • 使用擴展方法。我在添加ExtensionAttribute後試過,然後意識到它不起作用,因爲擴展方法無法訪問私有/受保護的變量。我最初認爲這確實是一個非常優雅的解決方案。 :(

我會很樂意聽取別人的想法。

+0

好問題...這將是有趣不得不等待,直到一個特定的日期找到你的測試失敗,因爲你依靠什麼「今天」的是,不能增加它:) – slugster 2010-03-20 05:40:42

+0

重複:HTTP: //stackoverflow.com/questions/2425721/unit-testing-datetime-now – 2010-03-20 11:14:04

+0

感謝您的所有輸入。日期時間提供者方法也是我應該考慮的事情。然而,在這種情況下,我認爲我會按照Gishu的方法行事 - 對我來說,這似乎是最少的工作,也是最不具有侵入性的。 – 2010-03-20 22:42:30

回答

1

我平時收集到的抽象/接口裏面的OS調用,這樣我可以輕鬆地測試它..正如安德魯如上所述。

但是隻給出在問題中提到的需要;我覺得'Subclass and Override'是完成這個任務的最簡單和侵入性最小的方式--OP提到的選項2。

public class DateCalculator 
{ 
    public DateTime GetNextExpirationDate() { // call to GetBaseLineDate() to determine result } 
    virtual protected GetBaseLineDate() { return DateTime.Today; } 
} 

// in your test assembly 
public class DateCalcWithSettableBaseLine : DateCalculator 
{ 
    public DateTime BaseLine { get; set;} 
    override protected GetBaseLineDate() 
    { return this.BaseLine; } 
} 
4

您可以使用提供基線日期的接口。通常你會使用返回DateTime.Today實現,但是出於測試目的有一個可以讓你的單元測試提供一個日期。

如果有必要使用當前日期DATEBASE服務器或其他一些機器,並不一定是你的代碼運行在這也可能是有用的。

事實上,這是與之相同的問題一些更詳細的答案比我:Unit Testing: DateTime.Now

1

一種選擇是創建一個內部過載這需要一個DateTime,並委託真正落實到:

public DateTime GetNextExpirationDate() 
{ 
    return GetNextExpirationDate(DateTime.Today); 
} 

internal DateTime GetNextExpirationDate(DateTime after) 
{ 
    // implementation goes here 
} 

然後可以使用InternalsVisibleToAttribute使超載可見到您的測試程序集,然後您的測試程序集可以使用它自己選擇的DateTime值調用它。

0

可以說在做測試的計算機上更改操作系統的時間,日曆時鐘。這很簡單,透明,但要注意文件時間戳的問題。