我正在寻找一个.NET Core中替代Microsoft Fakes的方案。我知道它在.NET Core中已不再受支持。我只是不明白为什么,我认为在某些情况下它是一个很好的解决方案。
我的问题是我想mock DateTime.Now。以前你可以使用以下代码来实现:
System.Fakes.ShimDateTime.NowGet = () =>
{
return new DateTime(2000, 1, 1);
};
该技术在Microsoft文档中有描述,详细信息请参见以下链接:https://learn.microsoft.com/en-us/visualstudio/test/using-shims-to-isolate-your-application-from-other-assemblies-for-unit-testing?view=vs-2017
目前,我通过创建一个DateTime的包装器来解决这个问题,如下所示:
/// <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;
}
}
我要感谢下面这篇StackOverflow的帖子提供的解决方案:Unit Testing: DateTime.Now
但我对这个解决方案还不满意,因为我觉得我必须根据我的测试来调整实现。我认为这是不可取的。
希望有人能帮助我,非常感谢您的努力。
DateTime.Now
(或者如果是另一个系统、平台等则是等价的)的硬依赖,以便您可以注入它。隐藏依赖关系是测试的祸根,因为...嗯...它们是隐藏的,即对您不可见,因此在设置新的测试场景时很容易被忽略。将其放在需要注入的抽象后面(您也应该这样做)使得此依赖关系变得可见,从而更容易处理。 - Lasse V. Karlsenstatic
,我通常会像 Lasse 一样将其实现为DateTimeProvider : IDateTimeProvider
。然后你的类就会显式地依赖于IDateTimeProvider
。这使得哪些类依赖于DateTime
变得非常清晰,因此需要进行模拟。从单元测试的角度来看,使用static
的缺点是你的测试无法并行化(因为只有一个static
值,所以如果不同的测试想要模拟不同的值,它们将互相干扰)。 - mjwills