代码之家  ›  专栏  ›  技术社区  ›  Kimi

Why there is no IDateTimeProvider in .NET and DateTime has Now getter?

  •  7
  • Kimi  · 技术社区  · 14 年前

    目前,我正在为执行特定于日期时间验证的组件编写单元测试。我创造了 IDateTimeProvider interface, that serves as a DateTime.UtcNow wraper and business objects use interface rather than DateTime 直接。似乎datetime有点超载,应该被拆分为一个值和一个从操作系统获取该值的东西。我想知道有没有特别的理由不 IDateTimeProvider ( IClock ).NET中的接口?

    4 回复  |  直到 9 年前
        1
  •  7
  •   Jon Skeet    14 年前

    Simply put: because large parts of the BCL weren't designed for testability.

    在“核心”功能方面,随机数生成也是如此,而且许多与HTTP相关的类更容易被伪造出来:(至少在这种情况下,引入自己的时钟接口是相当容易的)。

    On the plus side, when Noda Time 已准备好投入生产使用,它不仅提供比BCL更好的日期/时间API—它还提供了一个更易于测试的API:。

        2
  •  1
  •   Koen    14 年前

    我们始终使用一个DateTimeProvider包装类,如果需要,我们可以在测试上下文中重写它…

        3
  •  0
  •   hfrmobile    13 年前

    http://learn.typemock.com/typemock-isolator/ is able to mock DateTime ( 如此 日期时间 不再是问题了。但缺点当然是这可能导致开发人员设计他们的东西更糟糕,因为模仿日期时间是没有问题的。

    Maybe using something like IDateTimeProvider is a better solution for such things.

    但如果您使用的是第三方lib,它将在诸如datetime typemock isolatior之类的服务器上进行中继,那么可能需要解决方案/解决方案。

    Also Microsoft Research's Moles/Stub is cool stuff: http://channel9.msdn.com/blogs/peli/moles-replace-any-net-method-with-a-delegate (shows how to replace any .NET method/property with a delegate - e.g. DateTime.Now ;-))

        4
  •  0
  •   Matt Klein    9 年前

    我把这个答案贴到了另一个问题上,但如果你想找一个简单的测试方法,它也适用于这里。 DateTime.Now .

    What I like to do is create a public function that returns a DateTime ( Func<DateTime> )在需要当前日期/时间并将其设置为返回日期时间的类中。默认情况下,现在返回。然后,在测试期间,我用一个测试函数覆盖它,该函数返回我想要测试的任何日期时间。

    public class MyClass
    {
        public Func<DateTime> DateTimeNow = () => DateTime.Now;
    
        public void MyMethod()
        {
            var currentTime = DateTimeNow();
            //... do work
        }
    }
    
    public class MyClassTest
    {
        public void TestMyMethod()
        {
            // Arrange
            var myClass = new MyClass();
            myClass.DateTimeNow = () => new DateTime(1999, 12, 31, 23, 59, 59);
    
            // Act
            myClass.MyMethod();
    
            // Assert
            // my asserts
        }
    }