如何从 c# 代码动态更新服务器时间

问题描述

我有一个持续的测试管道,其中单元和集成测试必须在代码能够合并之前传递 PR。

它在减少错误和稳定我们的代码库方面做得很好,但我们遇到了时间问题

在周末,包含此堆栈的多个应用程序会进行明确检查,以防止在周末提交新订单。更糟糕的是,其中一些应用程序使用 DateTime.Now 进行这些检查,并且在没有大量重构的情况下无法模拟。

是否可以在 C# 中在我们的测试中发出一个命令来更新“服务器时间”,以便我们的大多数测试可以工作?

解决方法

简短的回答是否定的。如果你想调整一些基本的界面,你要么需要设置你的操作系统并在测试运行之前更改时间(这可能会产生非常不可预测的结果)或模拟它。其实很简单:

不要使用 DateTime.Now/UtcNow,而是使用您的显式版本。

public interface IDateTimeManager
{
    DateTime Now {get;}
}

代码库中的任何位置:

var now = _dateTimeManager.Now;

在测试设置中:

var mockDateTimeManager = new Mock<IDateTimeManager>();
mockDateTimeManager.Setup(x=> x.Now).Returns(new DateTime(2000,1,1));

在设置中:

var container = new Container();
container.RegisterSingleton<IDateTimeManager>(mockDateTimeManager.Object);

如果你是应用程序独立的可执行文件/服务,你可以传递一个参数来设置这个管理器的初始值:

myapp.exe --start-date "2000-01-01"

public interface IDateTimeManager
{
    DateTime UtcNow { get; }
}
internal sealed class DateTimeManager : IDateTimeManager
{
    private readonly DateTime _initialTime;
    private readonly DateTime _initialOsTime;
    public DateTime UtcNow => _initialTime + (DateTime.UtcNow - _initialOsTime);

    public DateTimeManager(DateTime initialTime)
    {
        _initialTime = initialTime;
        _initialOsTime = DateTime.UtcNow;

    }
}

附注

在这种情况下,控制反转是您最好的朋友。

我得出的结论是,将特定于操作系统的方法替换为我自己的接口更容易,而不是绕过测试环境。例如,在我的项目中,出于同样的原因,所有 File 命名空间经常被嘲笑。我可以通过这种方式模仿任何行为。

,

Try this

也就是说,使用适当的数据结构调用 WinAPI 函数 SetSystemTime

不要忘记将服务器时间返回“正确”!

[当然,假设您的服务器是 Windows,但您没有提及...]

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...