Skip to main content
dotnet-testing-datetime-testing-timeprovider 使用 TimeProvider 測試時間相依邏輯的專門技能。當需要測試 DateTime、控制時間流逝、處理時區轉換、測試過期邏輯時使用。涵蓋 TimeProvider 抽象化、FakeTimeProvider 時間控制、時間凍結與快轉等。
Make sure to use this skill whenever the user mentions DateTime testing, TimeProvider, FakeTimeProvider, time-dependent logic, cache expiration, or token expiration testing, even if they don't explicitly ask for time testing guidance.
Keywords: datetime, time testing, 時間測試, TimeProvider, FakeTimeProvider, DateTime.Now, 時間相依, 快取過期, token 過期, Microsoft.Bcl.TimeProvider, GetUtcNow, SetUtcNow, Advance, time freeze, 時間凍結, 時間快轉
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/kevintsengtw/dotnet-testing-agent-skills --skill dotnet-testing-datetime-testing-timeprovider命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... kevintsengtw
kevintsengtw/dotnet-testing-agent-skills
打开 GitHub 仓库 dotnet-testing-advanced-aspire-testing .NET Aspire Testing 整合測試框架完整指南。當需要測試 .NET Aspire 分散式應用程式、設定 AppHost 測試或從 Testcontainers 遷移至 Aspire 測試時使用。涵蓋 DistributedApplicationTestingBuilder、容器生命週期管理、多服務編排、Respawn 配置與時間可測試性設計。
Make sure to use this skill whenever the user mentions .NET Aspire, AppHost testing, DistributedApplicationTestingBuilder, cloud-native testing, or migrating from Testcontainers to Aspire, even if they don't explicitly ask for Aspire testing guidance.
Keywords: aspire testing, .NET Aspire, DistributedApplicationTestingBuilder, AppHost testing, 分散式測試, AspireAppFixture, IAsyncLifetime, ContainerLifetime.Session, 雲原生測試, 多服務整合, Aspire.Hosting.Testing, Respawn
dotnet-testing-advanced-aspnet-integration-testing ASP.NET Core 整合測試的專門技能。當需要測試 Web API 端點、HTTP 請求/回應、中介軟體、依賴注入時使用。涵蓋 WebApplicationFactory、TestServer、HttpClient 測試、記憶體資料庫配置等。
Make sure to use this skill whenever the user mentions ASP.NET Core integration testing, WebApplicationFactory, TestServer, HTTP endpoint testing, or middleware testing, even if they don't explicitly ask for integration testing guidance.
Keywords: integration testing, 整合測試, web api testing, WebApplicationFactory, TestServer, HttpClient testing, controller testing, endpoint testing, 端點測試, RESTful API testing, Microsoft.AspNetCore.Mvc.Testing, CreateClient, ConfigureWebHost, AwesomeAssertions.Web, Be200Ok, Be404NotFound, middleware testing, 中介軟體測試, dependency injection testing
.NET 進階測試技能總覽與引導中心。當使用者詢問「整合測試」、「API 測試」、「容器化測試」、「微服務測試」、「測試框架遷移」、「Testcontainers」、「Aspire 測試」等進階測試需求時觸發。會根據具體需求推薦適合的子技能組合,涵蓋整合測試、Testcontainers、Aspire 測試、框架升級等 8 個進階技能。
Make sure to use this skill whenever the user mentions integration testing, API testing, Testcontainers, .NET Aspire testing, WebApplicationFactory, or xUnit/TUnit migration, even if they don't explicitly ask for advanced testing guidance.
Keywords: integration testing, 整合測試, API testing, advanced testing, 進階測試, testcontainers, aspire testing, WebApplicationFactory, TestServer, database test, 資料庫測試, EF Core test, MongoDB test, Redis test, Docker test, 容器測試, microservice test, 微服務測試, .NET Aspire, xUnit upgrade, TUnit, framework migration
name dotnet-testing-datetime-testing-timeprovider description 使用 TimeProvider 測試時間相依邏輯的專門技能。當需要測試 DateTime、控制時間流逝、處理時區轉換、測試過期邏輯時使用。涵蓋 TimeProvider 抽象化、FakeTimeProvider 時間控制、時間凍結與快轉等。
Make sure to use this skill whenever the user mentions DateTime testing, TimeProvider, FakeTimeProvider, time-dependent logic, cache expiration, or token expiration testing, even if they don't explicitly ask for time testing guidance.
Keywords: datetime, time testing, 時間測試, TimeProvider, FakeTimeProvider, DateTime.Now, 時間相依, 快取過期, token 過期, Microsoft.Bcl.TimeProvider, GetUtcNow, SetUtcNow, Advance, time freeze, 時間凍結, 時間快轉
DateTime 與時間相依性測試指南
核心原則
原則一:時間抽象化 - 以 TimeProvider 取代 DateTime
傳統問題程式碼 :
public class OrderService
{
public bool CanPlaceOrder ()
{
var now = DateTime.Now;
return now.Hour >= 9 && now.Hour < 17 ;
}
}
可測試的重構 :
public class OrderService
{
private readonly TimeProvider _timeProvider;
public OrderService (TimeProvider timeProvider )
{
_timeProvider = timeProvider ?? ArgumentNullException( (timeProvider));
}
{
now = _timeProvider.GetLocalNow();
now.Hour >= && now.Hour < ;
}
}
throw
new
nameof
public bool CanPlaceOrder ()
var
return
9
17
services.AddSingleton(TimeProvider.System);
services.AddScoped<OrderService>();
原則二:FakeTimeProvider 控制測試時間 FakeTimeProvider 提供完整的時間控制能力:
方法 用途 使用時機 SetUtcNow(DateTimeOffset)設定 UTC 時間 需要精確 UTC 時間時 SetLocalTimeZone(TimeZoneInfo)設定本地時區 測試時區相關邏輯 Advance(TimeSpan)時間快轉 測試過期、延遲邏輯 GetUtcNow()取得 UTC 時間 讀取當前模擬時間 GetLocalNow()取得本地時間 讀取本地模擬時間
public static class FakeTimeProviderExtensions
{
public static void SetLocalNow (this FakeTimeProvider fakeTimeProvider, DateTime localDateTime )
{
fakeTimeProvider.SetLocalTimeZone(TimeZoneInfo.Local);
var utcTime = TimeZoneInfo.ConvertTimeToUtc(localDateTime, TimeZoneInfo.Local);
fakeTimeProvider.SetUtcNow(utcTime);
}
}
原則三:每個測試使用獨立的時間環境
public class OrderServiceTests
{
[Fact ]
public void CanPlaceOrder_在營業時間內_應回傳True()
{
var fakeTimeProvider = new FakeTimeProvider();
fakeTimeProvider.SetLocalNow(new DateTime(2024 , 3 , 15 , 14 , 0 , 0 ));
var sut = new OrderService(fakeTimeProvider);
var result = sut.CanPlaceOrder();
result.Should().BeTrue();
}
}
public class BadTestClass
{
private static readonly FakeTimeProvider SharedProvider = new ();
}
進階時間控制技術
時間凍結 [Fact ]
public void ProcessBatch_在固定時間點_應產生相同時間戳()
{
var fakeTimeProvider = new FakeTimeProvider();
var fixedTime = new DateTime(2024 , 12 , 25 , 10 , 30 , 0 );
fakeTimeProvider.SetLocalNow(fixedTime);
var processor = new BatchProcessor(fakeTimeProvider);
var result1 = processor.ProcessItem("Item1" );
var result2 = processor.ProcessItem("Item2" );
result1.Timestamp.Should().Be(result2.Timestamp);
}
時間快轉 (Advance) [Fact ]
public void Cache_經過過期時間_應清除項目()
{
var fakeTimeProvider = new FakeTimeProvider();
fakeTimeProvider.SetLocalNow(new DateTime(2024 , 3 , 15 , 10 , 0 , 0 ));
var cache = new TimedCache(fakeTimeProvider, TimeSpan.FromMinutes(5 ));
cache.Set("key" , "value" );
fakeTimeProvider.Advance(TimeSpan.FromMinutes(3 ));
cache.Get("key" ).Should().Be("value" );
fakeTimeProvider.Advance(TimeSpan.FromMinutes(3 ));
cache.Get("key" ).Should().BeNull();
}
重要 :Advance() 是非阻塞的,瞬間完成時間跳躍,不會真正等待。
時間倒轉 [Fact ]
public void HistoricalDataProcessor_回到過去時間_應正確處理()
{
var fakeTimeProvider = new FakeTimeProvider();
var historicalTime = new DateTime(2020 , 1 , 15 , 9 , 0 , 0 );
fakeTimeProvider.SetLocalNow(historicalTime);
var processor = new HistoricalDataProcessor(fakeTimeProvider);
var result = processor.ProcessDataForDate(historicalTime.Date);
result.ProcessedAt.Should().Be(historicalTime);
}
實戰測試模式
模式一:參數化邊界測試 [Theory ]
[InlineData(8, false) ]
[InlineData(9, true) ]
[InlineData(12, true) ]
[InlineData(16, true) ]
[InlineData(17, false) ]
[InlineData(18, false) ]
public void CanPlaceOrder_不同時間點_應回傳正確結果(int hour, bool expected)
{
var fakeTimeProvider = new FakeTimeProvider();
fakeTimeProvider.SetLocalNow(new DateTime(2024 , 3 , 15 , hour, 0 , 0 ));
var sut = new OrderService(fakeTimeProvider);
sut.CanPlaceOrder().Should().Be(expected);
}
模式二:交易時間窗口測試 [Theory ]
[InlineData("09:30:00" , true) ]
[InlineData("12:00:00" , false) ]
[InlineData("14:30:00" , true) ]
[InlineData("15:30:00" , false) ]
public void IsInTradingHours_不同時間_應回傳正確結果(string timeStr, bool expected)
{
var fakeTimeProvider = new FakeTimeProvider();
var testTime = DateTime.Today.Add(TimeSpan.Parse(timeStr));
fakeTimeProvider.SetLocalNow(testTime);
var sut = new TradingService(fakeTimeProvider);
sut.IsInTradingHours().Should().Be(expected);
}
模式三:排程觸發邏輯測試 [Theory ]
[InlineData("2024-03-15 14:30:00" , "2024-03-15 14:00:00" , true) ]
[InlineData("2024-03-15 13:30:00" , "2024-03-15 14:00:00" , false) ]
public void ShouldExecuteJob_根據時間判斷_應回傳正確結果(
string currentTimeStr, string scheduledTimeStr, bool expected)
{
var fakeTimeProvider = new FakeTimeProvider();
fakeTimeProvider.SetLocalNow(DateTime.Parse(currentTimeStr));
var schedule = new JobSchedule { NextExecutionTime = DateTime.Parse(scheduledTimeStr) };
var sut = new ScheduleService(fakeTimeProvider);
sut.ShouldExecuteJob(schedule).Should().Be(expected);
}
AutoFixture 整合
FakeTimeProviderCustomization public class FakeTimeProviderCustomization : ICustomization
{
public void Customize (IFixture fixture )
{
fixture.Register(() => new FakeTimeProvider());
}
}
AutoDataWithCustomization 屬性 public class AutoDataWithCustomizationAttribute : AutoDataAttribute
{
public AutoDataWithCustomizationAttribute () : base (CreateFixture )
{
}
private static IFixture CreateFixture ()
{
return new Fixture()
.Customize(new AutoNSubstituteCustomization())
.Customize(new FakeTimeProviderCustomization());
}
}
使用 Matching.DirectBaseType [Theory ]
[AutoDataWithCustomization ]
public void GetTimeBasedDiscount_週五_應回傳九折優惠(
[Frozen(Matching.DirectBaseType) ] FakeTimeProvider fakeTimeProvider,
OrderService sut)
{
var fridayTime = new DateTime(2024 , 3 , 15 , 14 , 0 , 0 );
fakeTimeProvider.SetLocalNow(fridayTime);
sut.GetTimeBasedDiscount().Should().Be("週五快樂:九折優惠" );
}
關鍵 :必須使用 [Frozen(Matching.DirectBaseType)],否則 AutoFixture 無法正確將 FakeTimeProvider 注入到需要 TimeProvider 的建構式中。
最佳實踐檢查清單
程式碼設計
測試設計
進階考量
輸出格式
產生使用 TimeProvider 抽象的服務類別
產生使用 FakeTimeProvider 的測試類別
包含時間凍結、快轉、時區轉換測試範例
提供 .csproj 套件參考(Microsoft.Bcl.TimeProvider)
參考資源
原始文章 本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章:
Day 16 - 測試日期與時間:Microsoft.Bcl.TimeProvider 取代 DateTime
官方文件
相關技能
autofixture-basics - AutoFixture 自動測試資料生成
nsubstitute-mocking - 測試替身與模擬
autodata-xunit-integration - xUnit 與 AutoFixture 的 AutoData 整合