Cra*_*col 109 c# testing datetime unit-testing
我有一些(C#)代码依赖于今天的日期来正确计算未来的东西.如果我在测试中使用今天的日期,我必须在测试中重复计算,这感觉不对.在测试中将日期设置为已知值的最佳方法是什么,以便我可以测试结果是否为已知值?
Bla*_*rad 149
我的偏好是让使用时间的类实际上依赖于接口,例如
interface IClock
{
    DateTime Now { get; } 
}
具体实施
class SystemClock: IClock
{
     DateTime Now { get { return DateTime.Now; } }
}
然后,如果您愿意,您可以提供您想要测试的任何其他类型的时钟,例如
class StaticClock: IClock
{
     DateTime Now { get { return new DateTime(2008, 09, 3, 9, 6, 13); } }
}
为依赖它的类提供时钟可能会有一些开销,但可以通过任意数量的依赖注入解决方案来处理(使用Inversion of Control容器,普通的构造函数/ setter注入,甚至静态网关模式)).
提供提供所需时间的对象或方法的其他机制也有效,但我认为关键是避免重置系统时钟,因为这只会引入其他级别的痛苦.
此外,DateTime.Now在您的计算中使用和包含它不仅感觉不对 - 它会使您无法测试特定时间,例如,如果您发现仅在午夜边界附近或周二发生的错误.使用当前时间将不允许您测试这些方案.或者至少不是随时随地.
Ant*_*ean 55
Ayende Rahien 使用一种相当简单的静态方法......
public static class SystemTime
{
    public static Func<DateTime> Now = () => DateTime.Now;
}
mmi*_*uva 16
使用Microsoft Fakes创建填充程序是一种非常简单的方法.假设我有以下课程:
public class MyClass
{
    public string WhatsTheTime()
    {
        return DateTime.Now.ToString();
    }
}
在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);
        }
    }
}
}
Jay*_*uzi 11
成功进行单元测试的关键是解耦.您必须将有趣的代码与其外部依赖项分开,因此可以单独进行测试.(幸运的是,测试驱动开发产生了解耦代码.)
在这种情况下,您的外部是当前的DateTime.
我的建议是将处理DateTime的逻辑提取到一个新的方法或类或在你的情况下有意义,并传递DateTime.现在,你的单元测试可以传递一个任意的DateTime,以产生可预测的结果.
Joã*_*elo 10
另一个使用Microsoft Moles(.NET的隔离框架).
MDateTime.NowGet = () => new DateTime(2000, 1, 1);
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);
    } 
}
详细描述在这里:http : //www.lesnikowski.com/blog/index.php/testing-datetime-now/
| 归档时间: | 
 | 
| 查看次数: | 34434 次 | 
| 最近记录: |