選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
2 分鐘閱讀時間 (447 個字)

善用-net-8-控制時間相關的測試

善用-net-8-控制時間相關的測試

過去有些程式與時間相關,測試並不好做。例如以下的受測程式:

public static string Greeting()
{
    string returnValue = "Good Evening!";
    DateTimeOffset dateTimeOffset = DateTimeOffset.Now;
    int hour = dateTimeOffset.Hour;
    if (hour > 4)
    {
        if (hour > 11)
        {
            if (hour < 18)
            {
                returnValue = "Good Afternoon!";
            }
        }
        else
        {
            returnValue = "Good Morning!";
        }
    }
    return returnValue;
}

如果我的測試是這麼寫:

string greeting = Program.Greeting();
Assert.Equal("Good Afternoon!", greeting);

很明顥地,只能在下午進行測試才會通過。其中的關鍵,就是程式中呼叫到「現在」這種與時間相關的,諸如

  • DateTime.Now
  • DateTime.UtcNow
  • DateTimeOffset.Now
  • DateTimeOffset.UtcNow
都是。不過這種困境到了 .NET 8 有所改善,我們可以先在測試專案引用必要的元件(版本可能隨時間而改變):
  • dotnet add package Microsoft.Extensions.TimeProvider.Testing --version 8.5.0
接著稍微修改我們的受測程式(其實修改只集中在前九行):
public static string GreetingV2(System.TimeProvider? timeProvider)
{
    string returnValue = "Good Evening!";
    System.TimeProvider _timeProvider = System.TimeProvider.System;
    if (timeProvider != null)
    {
        _timeProvider = timeProvider;
    }
    DateTimeOffset dateTimeOffset = _timeProvider.GetLocalNow();
    int hour = dateTimeOffset.Hour;
    if (hour > 4)
    {
        if (hour > 11)
        {
            if (hour < 18)
            {
                returnValue = "Good Afternoon!";
            }
        }
        else
        {
            returnValue = "Good Morning!";
        }
    }
    return returnValue;
}

同時調整測試程式的寫法:

DateTimeOffset dateTimeOffset = new(2024, 5, 15, 16, 58, 0, TimeZoneInfo.Local.BaseUtcOffset);
TimeProvider fakeTimeProvider = new Microsoft.Extensions.Time.Testing.FakeTimeProvider(dateTimeOffset);
string greeting = Program.GreetingV2(fakeTimeProvider);
Assert.Equal("Good Afternoon!", greeting);

如此一來,不論未來何時執行測試程式,「現在」都固定在設計下的時間點,而且受影響的原程式範圍也縮限到非常小,還算不錯吧?

組件版本自動取號,與-swaggerdoc-上的呈現
為何導入 GitLab CI/CD?
 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2025/06/09, 週一

Captcha 圖像