Cra*_*col 109 c# testing datetime unit-testing
我有一些(C#)代码依赖于今天的日期来正确计算未来的东西.如果我在测试中使用今天的日期,我必须在测试中重复计算,这感觉不对.在测试中将日期设置为已知值的最佳方法是什么,以便我可以测试结果是否为已知值?
Bla*_*rad 149
我的偏好是让使用时间的类实际上依赖于接口,例如
interface IClock
{
DateTime Now { get; }
}
Run Code Online (Sandbox Code Playgroud)
具体实施
class SystemClock: IClock
{
DateTime Now { get { return DateTime.Now; } }
}
Run Code Online (Sandbox Code Playgroud)
然后,如果您愿意,您可以提供您想要测试的任何其他类型的时钟,例如
class StaticClock: IClock
{
DateTime Now { get { return new DateTime(2008, 09, 3, 9, 6, 13); } }
}
Run Code Online (Sandbox Code Playgroud)
为依赖它的类提供时钟可能会有一些开销,但可以通过任意数量的依赖注入解决方案来处理(使用Inversion of Control容器,普通的构造函数/ setter注入,甚至静态网关模式)).
提供提供所需时间的对象或方法的其他机制也有效,但我认为关键是避免重置系统时钟,因为这只会引入其他级别的痛苦.
此外,DateTime.Now在您的计算中使用和包含它不仅感觉不对 - 它会使您无法测试特定时间,例如,如果您发现仅在午夜边界附近或周二发生的错误.使用当前时间将不允许您测试这些方案.或者至少不是随时随地.
Ant*_*ean 55
Ayende Rahien 使用一种相当简单的静态方法......
public static class SystemTime
{
public static Func<DateTime> Now = () => DateTime.Now;
}
Run Code Online (Sandbox Code Playgroud)
mmi*_*uva 16
使用Microsoft Fakes创建填充程序是一种非常简单的方法.假设我有以下课程:
public class MyClass
{
public string WhatsTheTime()
{
return DateTime.Now.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
在Visual Studio 2012中,您可以通过右键单击要为其创建Fakes/Shims的程序集并选择"Add Fakes Assembly",将Fakes程序集添加到测试项目中.

最后,这是测试类的样子:
using System;
using ConsoleApplication11;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace DateTimeTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestWhatsTheTime()
{
using(ShimsContext.Create()){
//Arrange
System.Fakes.ShimDateTime.NowGet =
() =>
{ return new DateTime(2010, 1, 1); };
var myClass = new MyClass();
//Act
var timeString = myClass.WhatsTheTime();
//Assert
Assert.AreEqual("1/1/2010 12:00:00 AM",timeString);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Jay*_*uzi 11
成功进行单元测试的关键是解耦.您必须将有趣的代码与其外部依赖项分开,因此可以单独进行测试.(幸运的是,测试驱动开发产生了解耦代码.)
在这种情况下,您的外部是当前的DateTime.
我的建议是将处理DateTime的逻辑提取到一个新的方法或类或在你的情况下有意义,并传递DateTime.现在,你的单元测试可以传递一个任意的DateTime,以产生可预测的结果.
Joã*_*elo 10
另一个使用Microsoft Moles(.NET的隔离框架).
MDateTime.NowGet = () => new DateTime(2000, 1, 1);
Run Code Online (Sandbox Code Playgroud)
Moles允许用委托替换任何.NET方法.Moles支持静态或非虚拟方法.Moles依赖于Pex的剖析器.
我建议使用 IDisposable 模式:
[Test]
public void CreateName_AddsCurrentTimeAtEnd()
{
using (Clock.NowIs(new DateTime(2010, 12, 31, 23, 59, 00)))
{
string name = new ReportNameService().CreateName(...);
Assert.AreEqual("name 2010-12-31 23:59:00", name);
}
}
Run Code Online (Sandbox Code Playgroud)
详细描述在这里:http : //www.lesnikowski.com/blog/index.php/testing-datetime-now/
| 归档时间: |
|
| 查看次数: |
34434 次 |
| 最近记录: |