在单元测试中处理DateTime.Now的策略 [英] Strategies for dealing with DateTime.Now in unit tests
问题描述
我的业务逻辑在星期六或星期日不执行某些功能。我希望我的单元测试能够验证是否执行了这些功能,但是测试将在周六/周日失败。
I have business logic that does not perform certain functions on Saturday or Sunday. I want my unit tests to verify that these functions are performed, but the tests will fail on Saturday/Sunday.
我认为最简单的方法是传递单元测试友好的消息,指出如果在星期六/星期日运行测试结果,则该测试结果无效。
I figure the easiest route is to have the unit tests convey a friendly message stating that the test results are not valid if they are run on Saturday/Sunday.
使用C#/ NUnit ...
With C# / NUnit...
Assert.That(
DateTime.Now.DayOfWeek != DayOfWeek.Sunday && DateTime.Now.DayOfWeek !=
DayOfWeek.Saturday, "This test cannot be run on Saturday or Sunday");
是否可以/建议尝试模拟日期?
Is it possible/advisable to try and mock the date? Are there other strategies for handling this scenario?
推荐答案
是否有可能/建议尝试模拟?日期?
Is it possible/advisable to try and mock the date?
是的,不仅建议这样做,而且还是唯一可靠地对代码进行单元测试的方法。假设您想测试以下(无意义的)方法:
Yes, not only that it is advisable but it is the only way to reliably unit test your code in isolation. Suppose that you wanted to test the following (meaningless) method:
public bool Foo()
{
return (DateTime.Now.DayOfWeek == DayOfWeek.Sunday);
}
很明显您无法测试它,因为它依赖于静态方法(更精确的是静态现在属性)。显然,像这样紧密耦合的组件不能单独进行单元测试。
It's more than obvious that you can't test it because it relies on a static method (the static Now property to be more precise). It's clear that components which are tightly coupled like this cannot be unit tested in isolation.
现在考虑这种改进(用构造函数DI分离关注点):
Now consider this improvement (separation of concerns with constructor DI):
private readonly Func<DateTime> _nowProvider;
public SomeClass(Func<DateTime> nowProvider)
{
_nowProvider = nowProvider;
}
public bool Foo()
{
return (_nowProvider().DayOfWeek == DayOfWeek.Sunday);
}
现在,单元测试变得更好,更容易。 SomeClass
不再取决于不确定的日期。在实际的应用程序中,您显然会实例化 SomeClass
:
Now that's much better and easier to unit test. SomeClass
no longer depends on a non-deterministic date. In the real application you would obviously instantiate SomeClass
like this:
var s = new SomeClass(() => DateTime.Now);
s.Foo();
在单元测试中,您将对其进行模拟,以便可以验证两种情况:
and in your unit test you will mock it so that you can verify both cases:
var subjectUnderTest = new SomeClass(() => new DateTime(2011, 1, 3));
var actual = subjectUnderTest.Foo();
// assertions, ...
这篇关于在单元测试中处理DateTime.Now的策略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!