【问题标题】:How can "today's date" be varied for unit testing purposes?出于单元测试的目的,如何改变“今天的日期”?
【发布时间】:2011-01-29 17:31:21
【问题描述】:

我使用针对 .NET 2.0 Framework 的 VS2008,并且,以防万一,不,我无法更改:)

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

在编写单元测试时,我意识到我想针对不同的“今天”日期测试 GetNextExpirationDate

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

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

我很想听听别人的想法。

【问题讨论】:

  • 好问题...不得不等到特定日期才能发现测试失败会很有趣,因为您依赖于“今天”的任何内容并且无法增加它:)
  • 感谢您的所有意见。日期时间提供者方法也是我应该考虑的。然而,在这种情况下,我想我会采用 Gishu 的方法——这似乎是我工作最少、侵入性最小的方法。

标签: c# unit-testing datetime


【解决方案1】:

您可以使用提供基准日期的界面。通常,您会使用返回 DateTime.Today 的实现,但出于测试目的,您可以使用一个让您的单元测试提供日期的实现。

如果需要在数据库服务器或其他不一定是运行代码的机器上使用当前日期,这也很有用。

事实上,这里有比我更详细的答案的同一个问题:Unit Testing: DateTime.Now

【讨论】:

    【解决方案2】:

    我通常在抽象/接口中收集对操作系统的调用,以便我可以轻松地对其进行测试。就像上面提到的 Andrew。

    但是仅考虑到问题中提到的需求;我觉得“子类和覆盖”是完成此任务的最简单且侵入性最小的方法 - 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;  }
    }
    

    【讨论】:

      【解决方案3】:

      一种选择是创建一个采用 DateTime 的内部重载,并将真正的实现委托给它:

      public DateTime GetNextExpirationDate()
      {
        return GetNextExpirationDate(DateTime.Today);
      }
      
      internal DateTime GetNextExpirationDate(DateTime after)
      {
        // implementation goes here
      }
      

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

      【讨论】:

        【解决方案4】:

        您可以在进行测试的计算机上更改操作系统的时钟。这既简单又透明,但要注意文件时间戳的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-12
          • 2018-01-31
          • 1970-01-01
          • 2018-04-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多