Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 应用程序时间的设计模式?_C#_Design Patterns_Testing - Fatal编程技术网

C# 应用程序时间的设计模式?

C# 应用程序时间的设计模式?,c#,design-patterns,testing,C#,Design Patterns,Testing,如果您构建的系统中的业务流程取决于时间[1],则不能在代码中使用DateTime.Now或类似内容,因为您将必须处理测试,例如,未来的月末或年末场景。当您使用SSL证书时,更改操作系统时间通常不是一个选项,因为对分布式系统进行正确操作很复杂 一个选项是创建一个可由所有系统访问并返回当前时间的单例服务。在生产中,它可以返回日期时间。现在,在测试中,它可以返回一个游戏时间,如月末场景中的2月28日 但是有没有更好的方法呢?是否喜欢更面向数据库的方法,因为它可以带来更好的性能?或者你会放在一个分布式缓

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

一个选项是创建一个可由所有系统访问并返回当前时间的单例服务。在生产中,它可以返回日期时间。现在,在测试中,它可以返回一个游戏时间,如月末场景中的2月28日

但是有没有更好的方法呢?是否喜欢更面向数据库的方法,因为它可以带来更好的性能?或者你会放在一个分布式缓存中?有什么著名的设计模式吗


[1]典型示例:保险系统、核心银行系统等实施的业务流程

处理此问题的一种方法是:

并在整个代码中使用此界面,而不是
DateTime.Now
。在生产中,您将使用其规范实现(或UTC变体):

例如,您可以在需要
IClock
的所有类中使用
SystemClock
作为默认值,并允许通过构造函数或setter注入其他实现

在测试中,您可以创建测试实现或使用模拟框架对其进行模拟。

您可以研究如何使用来实现您所说的内容

看这个稍加修改的例子

[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的代码以使其可测试。

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


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

如果日期和时间是关键和复杂的(特别是由于时区和DST),我想您提到的行业就是这样,您可能希望避免使用


野田佳彦拥有内置的单元测试功能,请参见

我得出结论,以下方法将有效:

单元测试:

  • 模拟框架,根据需要控制时间
集成测试、用户驱动测试和生产:

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


Lars

我喜欢在正常测试中使用类似于赝品的框架来控制时间。您还可以使用Unity从生产代码中提取时间,这意味着您可以在测试和DateTime.Now中注入游戏时间。但是,当您为金融部门构建更大的系统时,您不能完全依赖这种方法,因为这些类型的测试通常是用户驱动的。一个普通示例:管理员(可以是业务人员)将一组新的业务参数(如利率)上载到测试环境,并希望从业务角度验证系统的反应。他们必须能够改变时间。
public class SystemClock implements IClock {
  public DateTime Now { get { return DateTime.Now; } }
}
[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);
    }
}