2016-03-30 56 views
4

我將不勝感激關於如何正確測試使用DateTimeOffset實例的代碼的信息或示例。我知道測試必須是確定性的。正確使用DateTimeOffset對象的單元測試類的方法?

那麼,如何將應用程序與DateTimeOffset類隔離?我想,當然,希望能夠使用假DateTimeOffset.Now等

在我的測試中,我應該使用類似:

var myDate = new DateTimeOffset(2016, 3, 29, 12, 20, 35, 93, TimeSpan.FromHours(-3)); 

或者我會改爲使用包裝像MyCustomDateTimeOffset類? 我應該在我的代碼中完全不使用DateTimeOffset,而是使用包裝?

回答

7

正如fundamentals theorem說:

我們可以通過引入額外的間接級別解決任何問題。

你並不真的需要一個包裝,你所需要的只是避免DateTimeOffset.Now/DateTimeOffset.UtcNow

這裏有幾個方法,你可以搞定:

  • 如果使用依賴注入,寫一個IClock接口,其暴露Now/UtcNow性能。

    public interface IClock 
    { 
        DateTimeOffset Now { get; } 
        DateTimeOffset UtcNow { get; } 
    } 
    
    internal class Clock : IClock 
    { 
        public DateTimeOffset Now => DateTimeOffset.Now; 
        public DateTimeOffset UtcNow => DateTimeOffset.UtcNow; 
    } 
    

    在您的測試中,您只需按照自己的意願模擬界面即可。

  • 如果您寧願繼續使用靜態屬性,請寫一個靜態類型,比如說Clock,然後使用它。

    public static class Clock 
    { 
        internal static Func<DateTimeOffset> DateTimeOffsetProvider { get; set; } 
         =() => DateTimeOffset.Now; 
    
        public static DateTimeOffset Now => DateTimeOffsetProvider(); 
        public static DateTimeOffset UtcNow => DateTimeOffsetProvider().ToUniversalTime(); 
    } 
    

    在您的測試中,您可以用DateTimeOffsetProvider替代。

    這裏有一個.NET版本2:

    public static class Clock 
    { 
        internal delegate DateTimeOffset DateTimeOffsetProviderDelegate(); 
        internal static DateTimeOffsetProviderDelegate DateTimeOffsetProvider { get; set; } 
    
        public static DateTimeOffset Now { get { return DateTimeOffsetProvider(); } } 
        public static DateTimeOffset UtcNow { get { return DateTimeOffsetProvider().ToUniversalTime(); } } 
    
        static Clock() 
        { 
         DateTimeOffsetProvider = delegate() { return DateTimeOffset.Now; }; 
        } 
    } 
    
+0

謝謝,但第二個版本(我喜歡更多)與.NET 2.0項目一起工作?你知道是否有其他的方式來做.Net 2.0的嗎?謝謝 –

+0

爲了在.NET 2中使用,您只需要用自定義委託來替換'Func ',我在答案中添加了一些代碼。 –

1

正如你不會知道DateTimeOffSet.Now的值,那麼您不能斷言DateTimeOffSet.Now等於值。

你或許應該重構使用以下兩種方法之一:

  • 依賴注入
  • 接口和包裝

依賴注入(DI)

DI手段,而不是具有方法確定日期,你通過它。

這種方法。 。 。

public void DoSomething() 
{ 
    var now = DateTimeOffSet.Now; 
    // Do other stuff with the date 
} 

。 。 。會改變這種方法

public void DoSomething(DateTimeOffSet dtos) 
{ 
    // Do other stuff with the date 
} 

接口和包裝

你的其他選擇(雖然你到底會使用DI與此太)是創建一個接口和一個包裝。然後在你的對象中使用你的接口,而不是一個具體的DateTimeOffSet,這樣你就可以使用MOQ或其他測試庫來調用接口。查看SystemWrapper(https://github.com/jozefizso/SystemWrapper)項目的示例。

相關問題