如果构建业务流程取决于 [1] 的时间的系统,则不能在代码中使用DateTime.Now
或类似的代码,因为您必须处理测试例如,未来月末或年终场景。使用SSL证书时通常不能更改操作系统时间,因为对分布式系统执行更正是很复杂的。
一个选项是创建一个可以返回当前时间的所有系统都可访问的单件服务。在生产中,它可以返回DateTime.Now
,并且在测试中它可以在月末场景中返回2月28日的游戏时间。
但有更好的方法吗?就像更加面向数据库的方法,因为它可以带来更好的性能?或者你会放入分布式缓存?这有一些众所周知的设计模式吗?
[1] 典型案例:保险系统,核心银行系统实施的业务流程......
答案 0 :(得分:4)
解决此问题的一种方法是拥有clock interface:
public interface IClock {
DateTime Now { get; }
}
在整个代码中使用此界面,代替DateTime.Now
。在生产中,您将使用其规范实现(或UTC变体):
public class SystemClock implements IClock {
public DateTime Now { get { return DateTime.Now; } }
}
例如,您可以在需要SystemClock
的所有类中使用IClock
作为默认值,并允许通过构造函数或setter注入其他实现。
在测试中,您可以创建测试实现或使用模拟框架对其进行模拟。
答案 1 :(得分:2)
您可以考虑使用Microsoft Fakes来实现您所说的内容。
见这个稍微修改过的例子;
[TestMethod]
public void TestCurrentYear()
{
int fixedYear = 2000;
// Shims can be used only in a ShimsContext:
using (ShimsContext.Create())
{
// Arrange:
// Shim DateTime.Now to return a fixed date:
System.Fakes.ShimDateTime.NowGet =
() =>
{ return new DateTime(fixedYear, 1, 1); };
// Act:
int year = DateTime.Now.Year;
// Assert:
Assert.AreEqual(fixedYear, year);
}
}
这里的优点是您不必更改任何使用DateTime使其可测试的代码。
答案 2 :(得分:2)
日期和时间是关键且复杂的(特别是由于时区和DST),我想您所提及的行业就是这种情况,您可能希望避免DateTime
支持Noda time
Noda时间内置了单元测试功能,请参阅https://stackoverflow.com/a/14531915/360211
答案 3 :(得分:1)
对于单元测试,您应该能够存根,包括时间。一些模拟框架(例如Microsoft Shims)允许您覆盖DateTime.Now的行为。
对于集成/系统测试,我过去所做的是使用每个系统组件的配置设置,该配置设置指定要从真实DateTime使用的该组件的DateTime偏移量。这可以通过未记录的app.config设置来设置,如果设置不存在,则应用正常行为。但是,您需要小心,这不会引入任何漏洞。
答案 4 :(得分:0)
我已经得出结论,以下方法将起作用:
单元测试:
集成测试,用户驱动测试&生产:
以下是调用NTP服务器的C#代码:calling NTP server from C#
拉斯