TimeProvider - .Net 測試程式時間方法
Contents
在 .NET 專案中直接呼叫 DateTime.Now
、DateTimeOffset.Now
很直覺,但會讓單元測試難以驗證「時間相關」邏輯。本文整理 .NET 內建的 TimeProvider
與幾種常見做法,包含 DI 注入、自訂時區、以及傳統靜態 DateTimeProvider,協助你把時間抽象化、好測又好維護。
為什麼需要 TimeProvider
過去我也常直接用
DateTime.Now
,直到開始寫測試才發現時間很難「固定」。.NET 8 起微軟提供 TimeProvider
抽象層,能透過依賴注入傳入系統時間或假的時間來源(如 FakeTimeProvider
),讓測試可以完全掌控時間。官方定義與基本用法
|
|
|
|
Stopwatch 與 TimeProvider
在引入 TimeProvider
之前,若要高解析度計時,常用 System.Diagnostics.Stopwatch
:
|
|
TimeProvider.GetTimestamp()
內部同樣倚賴高解析度計時器,差別是它具備抽象化與可測試性。
透過 DI 注入 TimeProvider
|
|
|
|
自訂時區 TimeProvider(方法 1)
|
|
參考(LINQPad 分享):https://share.linqpad.net/r38r9ivo.linq
自訂時區 TimeProvider(方法 2)
備註
其實方法 1 就能滿足多數需求,以下為更彈性的作法,適合需要由設定檔指定時區時。
情境:主機時區是日本或 UTC,但業務邏輯需要台灣時區;不能動作業系統時區時,可自訂 TimeProvider
。
- 參考:Customize Application Time Zone with TimeProvider | NimblePros Blog
https://blog.nimblepros.com/blogs/time-provider-time-zones/
|
|
參考(LINQPad 分享):https://share.linqpad.net/xplcfbkh.linq
使用 FakeTimeProvider 撰寫測試(推薦)
|
|
靜態 DateTimeProvider(傳統做法)
強者同事寫的靜態 DateTimeProvider
,快取台灣時區,並提供常用轉換與建立函式:
|
|
其他參考文章
- How to use TimeProvider and FakeTimeProvider (time abstraction in .NET)
https://grantwinney.com/how-to-use-timeprovider-and-faketimeprovider/ - 什麼是 TimeProvider 類別 - .NET | Microsoft Learn
https://learn.microsoft.com/zh-tw/dotnet/standard/datetime/timeprovider-overview#faketimeprovider-implementation - Unit Test小技巧 : DateTime的Stub - 黃偉榮 - 博客园
https://www.cnblogs.com/hwade/archive/2010/09/14/DateTimeStub.html - NET8 時間抽象(RiCo 技術農場)
https://medium.com/ricos-note/net8-%E6%99%82%E9%96%93%E6%8A%BD%E8%B1%A1-f9a0de5fd727
彩蛋
- System.Text.Json default DateTimeZoneHandling 討論:
https://github.com/dotnet/runtime/issues/1566
資料抓出來還是得自己轉換
|
|
心智圖
mindmap
root((TimeProvider in .NET))
Why
測試可控性
移除 DateTime.Now 相依
Built-in APIs
GetLocalNow
GetUtcNow
GetTimestamp
GetElapsedTime
DI
透過相依性注入
測試傳入 FakeTimeProvider
Custom TimeZone
覆寫 LocalTimeZone
設定檔指定 TimeZoneId
FakeTimeProvider
推進時間 Advance
冷凍/模擬現在時間
Legacy Static Provider
台灣時區快取
建立 DateTime/DateTimeOffset
Tips
Stopwatch 對照
System.Text.Json 時區議題