2010-03-20 45 views
5

我使用VS2008的目标.NET 2.0框架,以防万一,我不能改变这一点:)单元测试目的如何改变“今天的日期”?

我有一个DateCalculator类。其方法GetNextExpirationDate尝试确定下一个到期日,内部使用DateTime.Today作为基准日期。

当我写单元测试时,我意识到,我想测试GetNextExpirationDate不同的“今天”的日期。

这样做的最好方法是什么?以下是我考虑过的一些替代方案:

  • 公开一个属性/重载方法,参数为baselineDate,仅在单元测试中使用它。在实际客户端代码中,忽略属性/重载方法而偏向于默认为baselineDateDateTime.Today的方法。我不愿意这样做,因为它使DateCalculator类的公共接口很尴尬。
  • 创建一个名为baselineDate保护字段在内部设置为DateTime.Today。测试时,从DateCalculator派生DateCalculatorForTesting,通过构造方法设置baslineDate。它保持公共接口清洁,但仍然不是很好 - baselineDate已被保护,并且需要派生类,两者都仅用于测试。
  • 使用扩展方法。我在添加ExtensionAttribute后试过,然后意识到它不起作用,因为扩展方法无法访问私有/受保护的变量。我最初认为这确实是一个非常优雅的解决方案。 :(

我会很乐意听取别人的想法。

+0

好问题...这将是有趣不得不等待,直到一个特定的日期找到你的测试失败,因为你依靠什么“今天”的是,不能增加它:) – slugster 2010-03-20 05:40:42

+0

重复:HTTP: //stackoverflow.com/questions/2425721/unit-testing-datetime-now – 2010-03-20 11:14:04

+0

感谢您的所有输入。日期时间提供者方法也是我应该考虑的事情。然而,在这种情况下,我认为我会按照Gishu的方法行事 - 对我来说,这似乎是最少的工作,也是最不具有侵入性的。 – 2010-03-20 22:42:30

回答

1

我平时收集到的抽象/接口里面的OS调用,这样我可以轻松地测试它..正如安德鲁如上所述。

但是只给出在问题中提到的需要;我觉得'Subclass and Override'是完成这个任务的最简单和侵入性最小的方式--OP提到的选项2。

public class DateCalculator 
{ 
    public DateTime GetNextExpirationDate() { // call to GetBaseLineDate() to determine result } 
    virtual protected GetBaseLineDate() { return DateTime.Today; } 
} 

// in your test assembly 
public class DateCalcWithSettableBaseLine : DateCalculator 
{ 
    public DateTime BaseLine { get; set;} 
    override protected GetBaseLineDate() 
    { return this.BaseLine; } 
} 
4

您可以使用提供基线日期的接口。通常你会使用返回DateTime.Today实现,但是出于测试目的有一个可以让你的单元测试提供一个日期。

如果有必要使用当前日期DATEBASE服务器或其他一些机器,并不一定是你的代码运行在这也可能是有用的。

事实上,这是与之相同的问题一些更详细的答案比我:Unit Testing: DateTime.Now

1

一种选择是创建一个内部过载这需要一个DateTime,并委托真正落实到:

public DateTime GetNextExpirationDate() 
{ 
    return GetNextExpirationDate(DateTime.Today); 
} 

internal DateTime GetNextExpirationDate(DateTime after) 
{ 
    // implementation goes here 
} 

然后可以使用InternalsVisibleToAttribute使超载可见到您的测试程序集,然后您的测试程序集可以使用它自己选择的DateTime值调用它。

0

可以说在做测试的计算机上更改操作系统的时间,日历时钟。这很简单,透明,但要注意文件时间戳的问题。