当代码根据当前日期处理日期时,测试应涵盖边缘情况,例如闰年以及更频繁的月份和年份边界.
在我们的代码中,我们总是在我们的类中深入了解当前日期DateTime.Now
(在我们的例子中是.NET).
你怎么能对这些代码进行单元测试?
这是依赖注入变得非常有用的地方吗?
这是暂时的,但显然下一个版本的Typemock将允许伪造 DateTime.Now
https://blog.typemock.com/2009/05/mockingfaking-datetimenow-in-unit-tests.html
在我们的代码中,我们总是使用DateTime.Now(在我们的例子中是.NET)提取当前日期.你怎么能对这些代码进行单元测试?
这是一种依赖关系,并且是一种非确定性的依赖关系.您需要将代码的责任分开一点.
之前:
有一些代码使用当前日期时间来执行X.
后:
应该有一些代码负责获取当前的日期时间.
应该有一些代码使用datetime来做X.
这两组代码不应相互依赖.
这种分离依赖关系的模式也适用于其他情况(数据库,文件系统等).
使用DI注入"当前日期和时间"肯定是一种过度杀伤力.我宁愿重构代码以在任意日期操作.也就是说,我改变function calculateRevenue()
了function calculateRevenueOn(datetime date)
.如果您需要计算除当前日期之外的某些日期,这将更容易测试和使用.
我使用了Oren Eini(又名Ayende Rahien)在他的博客中讨论的非常务实的方法处理测试中的时间.
有一个像这样的静态类:
public static class SystemTime { public static FuncNow = () => DateTime.Now; }
你的代码变成了:
Entity.LastChange = SystemTime.Now();
你的测试将成为:
SystemTime.Now = () => new DateTime(2000,1,1); repository.ResetFailures(failedMsgs); SystemTime.Now = () => new DateTime(2000,1,2); var msgs = repository.GetAllReadyMessages(); Assert.AreEqual(2, msgs.Length);
始终将核心日期处理逻辑(根据我的经验,通常很容易为此目的孤立)放入以日期作为参数的单独方法中.
然后,在您的生产代码中,您可以调用它们并将它们作为参数提供给当前日期,并且仍然可以在单元测试中测试边缘情况.
顺便说一句,我发现测试边缘情况的日期逻辑是非常重要的.它消除了(可能是灾难性的,参考Zune)你从未发现的错误.除了你提到的那些,夏令时转换也可能有问题.