我有一些单元测试,期望“当前时间”与DateTime不同。显然,我不想改变电脑的时间。
实现这一目标的最佳策略是什么?
我有一些单元测试,期望“当前时间”与DateTime不同。显然,我不想改变电脑的时间。
实现这一目标的最佳策略是什么?
当前回答
测试依赖于系统的代码。DateTime,系统.dll必须被模拟。
我知道有两个框架可以做到这一点。微软的假货和罩衫。
微软的假货需要visual studio 2012的最后通牒,直接从康普顿出来。
Smocks是一个开放源代码,非常容易使用。可以使用NuGet下载。
下面是System的一个模拟。DateTime:
Smock.Run(context =>
{
context.Setup(() => DateTime.Now).Returns(new DateTime(2000, 1, 1));
// Outputs "2000"
Console.WriteLine(DateTime.Now.Year);
});
其他回答
这些都是很好的答案,这是我在另一个项目中所做的:
用法:
获取今天的真实日期时间
var today = SystemTime.Now().Date;
而不是使用DateTime。现在,你需要使用SystemTime.Now()…这并不难改变,但这种解决方案可能并不适合所有项目。
时间旅行(让我们去5年后)
SystemTime.SetDateTime(today.AddYears(5));
获得我们虚假的“今天”(从“今天”开始算起5年)
var fakeToday = SystemTime.Now().Date;
重置日期
SystemTime.ResetDateTime();
/// <summary>
/// Used for getting DateTime.Now(), time is changeable for unit testing
/// </summary>
public static class SystemTime
{
/// <summary> Normally this is a pass-through to DateTime.Now, but it can be overridden with SetDateTime( .. ) for testing or debugging.
/// </summary>
public static Func<DateTime> Now = () => DateTime.Now;
/// <summary> Set time to return when SystemTime.Now() is called.
/// </summary>
public static void SetDateTime(DateTime dateTimeNow)
{
Now = () => dateTimeNow;
}
/// <summary> Resets SystemTime.Now() to return DateTime.Now.
/// </summary>
public static void ResetDateTime()
{
Now = () => DateTime.Now;
}
}
关于模拟DateTime有一个特别的注意事项。现在使用TypeMock…
DateTime的值。现在必须放置到一个变量中,以便正确地模拟。例如:
这行不通:
if ((DateTime.Now - message.TimeOpened.Value) > new TimeSpan(1, 0, 0))
然而,这样做:
var currentDateTime = DateTime.Now;
if ((currentDateTime - message.TimeOpened.Value) > new TimeSpan(1, 0, 0))
关于@crabcrusherclamcollector的回答,在EF查询中使用这种方法时存在问题。NotSupportedException: LINQ to Entities不支持LINQ表达式节点类型“Invoke”。我将实现修改为:
public static class SystemTime
{
private static Func<DateTime> UtcNowFunc = () => DateTime.UtcNow;
public static void SetDateTime(DateTime dateTimeNow)
{
UtcNowFunc = () => dateTimeNow;
}
public static void ResetDateTime()
{
UtcNowFunc = () => DateTime.UtcNow;
}
public static DateTime UtcNow
{
get
{
DateTime now = UtcNowFunc.Invoke();
return now;
}
}
}
测试依赖于系统的代码。DateTime,系统.dll必须被模拟。
我知道有两个框架可以做到这一点。微软的假货和罩衫。
微软的假货需要visual studio 2012的最后通牒,直接从康普顿出来。
Smocks是一个开放源代码,非常容易使用。可以使用NuGet下载。
下面是System的一个模拟。DateTime:
Smock.Run(context =>
{
context.Setup(() => DateTime.Now).Returns(new DateTime(2000, 1, 1));
// Outputs "2000"
Console.WriteLine(DateTime.Now.Year);
});
模拟对象。
一个模拟DateTime,返回适合您的测试的Now。