6

如果您构建的系统的业务流程取决于现在是什么时间[1],那么您不能DateTime.Now在代码中使用或类似的,因为您将不得不处理测试,例如,未来的月末或年末场景。当您使用 SSL 证书时,更改操作系统时间通常不是一种选择,因为对分布式系统进行更正很复杂。

一种选择是创建一个所有系统都可以访问的单例服务,该服务返回当前时间。在生产中它可能会返回DateTime.Now,在测试中它可能会在月底场景中返回像 2 月 28 日这样的游戏时间。

但是有更好的方法吗?喜欢更面向数据库的方法,因为它可以带来更好的性能?还是您会放入分布式缓存?是否有一些众所周知的设计模式?

[1]典型例子:保险系统、核心银行系统、...

4

5 回答 5

4

One way to deal with this issue is to have a clock interface:

public interface IClock {
  DateTime Now { get; }
}

And use this interface throughout your code, in place of DateTime.Now. In production, you'll use its canonical implementation (or a UTC variant):

public class SystemClock implements IClock {
  public DateTime Now { get { return DateTime.Now; } }
}

You can, e.g., use SystemClock as a default in all classes that need IClock and allow other implementations to be injected through constructors or setters.

In tests, you can create a test implementation or mock it with a mocking framework.

于 2013-10-15T11:01:01.297 回答
2

You could look into using Microsoft Fakes to achieve what you're talking about.

See this slightly modified example;

[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);
    }
}

The advantage here is that you don't have to change any code that uses DateTime to make it testable.

于 2013-10-15T11:02:08.300 回答
2

Where date and time is critical and complex (especially due to timezones and DST), which I imagine is the case in the industries you mentioned, you might want to avoid DateTime in favour of Noda time.

Noda time has unit testing capabilities built in see https://stackoverflow.com/a/14531915/360211

于 2013-10-15T11:25:36.610 回答
1

对于单元测试,您应该能够删除任何内容,包括时间。一些模拟框架(例如Microsoft Shims)允许您覆盖 DateTime.Now 的行为。

对于集成/系统测试,我过去所做的是为每个系统组件使用一个配置设置,该设置为该组件指定一个从真实 DateTime 使用的 DateTime 偏移量。这可以通过未记录的 app.config 设置进行设置,如果该设置不存在,则应用正常行为。但是,您需要注意这不会引入任何漏洞。

于 2013-10-15T11:07:13.733 回答
0

我已经得出以下结论:

单元测试:

  • 模拟框架,根据需要控制时间

集成测试、用户驱动测试和生产:

  • 依赖注入,用于注入测试方法或生产方法
  • 测试方法:向 NTP 服务器询问现在几点。此 NTP 服务器将连接到所有相关应用程序,而不是拥有自己的服务器。NTP 服务器将具有一个标准接口,允许测试门户或管理员工具等程序根据需要对其进行更改。
  • 制作方法:询问系统时间,即从NTP服务器连接到所有服务器的时间

这是调用 NTP 服务器的 C# 代码:从 C# 调用 NTP 服务器

拉斯

于 2013-10-16T10:32:42.593 回答