单元测试依赖于 DateTime.Now 的挑战与应对策略
单元测试依赖当前时间的代码往往比较棘手,因为 DateTime.Now 的值是动态变化的。手动更改系统时间不可取,因此需要有效的解决方案。
最佳实践是隔离当前时间抽象,并将其注入到使用者中。这样,可以在单元测试中操控时间,而不会影响底层系统。
另一种方法是定义一个时间抽象作为环境上下文。这种方法涉及创建一个静态类,该类提供对当前时间的访问,并允许在测试期间用模拟对象替换它。
以下代码片段定义了一个作为环境上下文的 TimeProvider:
<code class="language-csharp">public abstract class TimeProvider { private static TimeProvider current = DefaultTimeProvider.Instance; public static TimeProvider Current { get { return TimeProvider.current; } set { if (value == null) { throw new ArgumentNullException("value"); } TimeProvider.current = value; } } public abstract DateTime UtcNow { get; } public static void ResetToDefault() { TimeProvider.current = DefaultTimeProvider.Instance; } }</code>
TimeProvider 的使用方法如下:
<code class="language-csharp">var now = TimeProvider.Current.UtcNow;</code>
在单元测试中,可以使用模拟对象替换 TimeProvider.Current:
<code class="language-csharp">var timeMock = new Mock<TimeProvider>(); timeMock.SetupGet(tp => tp.UtcNow).Returns(new DateTime(2010, 3, 11)); TimeProvider.Current = timeMock.Object;</code>
务必记住,在每次测试后将 TimeProvider 重置为其默认状态。这确保后续单元测试不受更改的时间抽象的影响。
以上是如何有效地对依赖于 DateTime.Now 的代码进行单元测试?的详细内容。更多信息请关注PHP中文网其他相关文章!