過去有些程式與時間相關,測試並不好做。例如以下的受測程式:
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);很明顥地,只能在下午進行測試才會通過。其中的關鍵,就是程式中呼叫到「現在」這種與時間相關的,諸如
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);
如此一來,不論未來何時執行測試程式,「現在」都固定在設計下的時間點,而且受影響的原程式範圍也縮限到非常小,還算不錯吧?
When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.
評論