為什麼要寫一個DateTime的Stub呢?
在有些情況必需判斷今天,如不同的節日,不同的Logo,因為System.DateTime.Now或Today,沒有辦法模擬,寫Unit Test時就沒有辦法測各個時間點的反應,總不可能做個測試要改系統時間吧。
建立DateTImeProdiver的虛擬類別,來包裝DateTime,有二個實作DefaultDateTimeProdiver是一般的Code使用,TestDateTimeProvider是Test的Code使用。
圖一 DateTiemProdiver的類別圖
使用
所有呼叫System.DateTime.Now或Today,都改成用System.DateTimeProdiver.Current.Now或Today,為了方便測試,改變一點寫法不為過吧。
1 | DateTime today = DateTimeProvider.Current.Today;< br > |
測試時
1 2 3 4 5 6 | //測試時改變DateTimeProvider的實例,以便摸擬不同時間的變化 DateTimeProvider.Current = new TestDateTimeProvider(new DateTime(2010, 1, 1)); Assert.AreEqual(LogoHelper.GetLogo(),"元旦.png"); DateTimeProvider.Current = new TestDateTimeProvider(new DateTime(2010, 2, 14)); Assert.AreEqual(LogoHelper.GetLogo(), "情人節.png"); |
原始碼
DateTImeProdiver與DefaultDateTimeProdiver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | //使用System,方便呼叫 namespace System { /// < summary > /// 為了單元測試增加的提供者,如DateTime.Now,無法Mock,所以多一層以便測試 /// </ summary > public abstract class DateTimeProvider { /// < summary > /// 預設的DateTimeProvider /// </ summary > private class DefaultDateTimeProvider : DateTimeProvider { /// < summary > /// 使用獨體模式 /// </ summary > private static DateTimeProvider instance; static DefaultDateTimeProvider() { instance = new DefaultDateTimeProvider(); } public static DateTimeProvider Instance { get { return instance; } } public override DateTime Now { get { return DateTime.Now; } } public override DateTime UtcNow { get { return DateTime.UtcNow; } } public override DateTime Today { get { return DateTime.Today; } } } /// < summary > /// 預設使用DefaultDateTimeProvider的獨體值 /// </ summary > private static DateTimeProvider current = DefaultDateTimeProvider.Instance; /// < summary > /// 可替換成別的DateTimeProvider /// </ summary > public static DateTimeProvider Current { get { return DateTimeProvider.current; } set { if (value == null) { throw new ArgumentNullException("value"); } DateTimeProvider.current = value; } } public abstract DateTime Now { get; } public abstract DateTime UtcNow { get; } public abstract DateTime Today { get; } } } |
TestDateTImeProdiver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /// < summary > /// 測試專用的DateTimeProvider /// </ summary > public class TestDateTimeProvider : DateTimeProvider { private DateTime datetime; public TestDateTimeProvider(DateTime datetime) { this.datetime = datetime; } public override DateTime Now { get { return datetime; } } public override DateTime UtcNow { get { return datetime.ToUniversalTime(); } } public override DateTime Today { get { return datetime.Date; } } } |
參考資料
标签:
Test
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?