Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.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#_Windows Services_Mocking - Fatal编程技术网

C# 模拟计算机系统日期时间

C# 模拟计算机系统日期时间,c#,windows-services,mocking,C#,Windows Services,Mocking,我用C#构建了一个Windows服务,它根据当前日期和时间从数据库调用实时时间序列数据。 我在测试数据库中有测试数据,我想用它来计算数据是否以正确的方式使用。 我想知道是否有人使用了一个应用程序或有任何其他方式来“模拟”您的本地计算机上的系统日期。例如,我可以运行这个应用程序并将其设置为将我的系统日期设置为指定日期 任何建议都很好。我现在已经使用它来覆盖,例如在运行测试时。在实际实现中,您使用DateTime.Now,现在使用新的SystemTime.Now。在测试中,您只需将Now设置为返回所

我用C#构建了一个Windows服务,它根据当前日期和时间从数据库调用实时时间序列数据。
我在测试数据库中有测试数据,我想用它来计算数据是否以正确的方式使用。
我想知道是否有人使用了一个应用程序或有任何其他方式来“模拟”您的本地计算机上的系统日期。例如,我可以运行这个应用程序并将其设置为将我的系统日期设置为指定日期


任何建议都很好。

我现在已经使用它来覆盖,例如在运行测试时。在实际实现中,您使用DateTime.Now,现在使用新的SystemTime.Now。在测试中,您只需将Now设置为返回所选值的不同函数

public static class SystemTime
{
    private static Func<DateTime> now = () => DateTime.Now;

    public static Func<DateTime> Now
    {
        get { return now; }
        set { now = value; }
    }
}
在单元测试拆卸中,重要的是使用
SystemTime.Now=()=>DateTime.Now将其设置回原来的值

正常使用:

DateTime now = SystemTime.Now();

只需将对
DateTime.Now
属性的访问封装在接口后面

public interface IDateTimeProvider
{
    DateTime Now { get; }
}
在代码中,使用如下实现:

public class DateTimeProvider : IDateTimeProvider
{
    public DateTime Now { get { return DateTime.Now; } }
}
对于您的测试,您可以通过创建测试类或使用模拟框架来模拟
IDateTimeProvider

如果您将此接口与依赖注入之类的技术一起使用,那么即使在运行时也很容易改变服务的行为

例如,您可以创建一个总是有几个小时休息的
IDateTimeProvider

public class AlwaysToLateDateTimeProvider : IDateTimeProvider
{
    public DateTime Now { get { return DateTime.Now.AddHours(-2); } }
}
或者创建一个从文件、数据库、管道等读取“模拟”日期时间的实现

在测试时,您可以将服务配置为使用其中一种实现,在实时模式下运行时,只需将依赖项注入配置为使用返回“正确”日期时间的普通实现即可


当然还有


与Mharlin的解决方案非常相似,下面的实现提供了对
DateTime.Now
的一对一替换。增加了一些在单元测试中操纵时间的方便方法。修改的是需要显式执行返回
DateTime
的操作,该操作与
DateTime.Now
用法更为相似

public static class SystemTime
{
    private static Func<DateTime> now = () => DateTime.Now;

    public static DateTime Now
    {
        get { return now(); }
    }

    public static void Set(DateTime dt)
    {
        now = () => dt;
    }

    public static void MoveForward(TimeSpan ts)
    {
        var dt = now().Add(ts);
        Set(dt);
    }

    public static void Reset()
    {
        now = () => DateTime.Now;
    }
}
时间敏感测试中的使用示例(此测试验证缓存过期):


你的意思是
如何模拟DateTime。现在在单元测试中?
看看单元测试。我已经在单元测试中模拟了时间来测试不同的逻辑,但现在我真的想在本地计算机上运行windows服务,看看它是否实现了我期望的所有功能。+1是个好主意。如果使用此代码,使舒尔在unittest拆卸代码中恢复now lamda表达式的原始值。否则,根据previos运行测试,其他单元测试可能会显示意外的结果。由于此处所建议的是单例性质,当并行运行依赖于时间的单元测试时,这也会失败。这个问题的真正解决方案是使用Moles/Fakes或TypeMock这样的东西,以便在不改变现有代码的情况下快速简便地解决问题。否则,您可能会谈论重构大量现有代码,以使用类似于JonathanK对依赖项注入Faik的响应的东西,因为DateTime.Now是非虚拟的,那么您将需要付费版本的TypeMock Isolator,以便在这样调用时使用。
Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2008, 1, 1));
public static class SystemTime
{
    private static Func<DateTime> now = () => DateTime.Now;

    public static DateTime Now
    {
        get { return now(); }
    }

    public static void Set(DateTime dt)
    {
        now = () => dt;
    }

    public static void MoveForward(TimeSpan ts)
    {
        var dt = now().Add(ts);
        Set(dt);
    }

    public static void Reset()
    {
        now = () => DateTime.Now;
    }
}
var twentyMinutesFromNow = SystemTime.Now.AddMinutes(20);
// Set(): effectively lock the system clock at a specific time
SystemTime.Set(new DateTime(2015, 1, 1));

RunCodeThatFetchesDataAndCachesIt();

// MoveForward(): easily move the clock relative to current time with an
//  arbitrary TimeSpan
SystemTime.MoveForward(TimeSpan.FromMinutes(1));

RunCodeThatFetchesDataAndCachesIt();
VerifyExpectationThatDataWasFetchedTwice();

// Reset(): return to the normal behavior of returning the current
//   DateTime.Now value
SystemTime.Reset();