【问题标题】:DateTime Interface to be used for unit testing用于单元测试的 DateTime 接口
【发布时间】:2015-10-29 13:55:53
【问题描述】:

你好,所以我创建了一个这样的日期时间接口:

public interface ITimeProvider<T>
{
    T Now { get; }
    string ToShortDateString();
}

然后我有一个这样的接口的实现:

public class DateTimeProvider : ITimeProvider<DateTime>
{

    private DateTime _date;

    public DateTime Now
    {
        get { return DateTime.Now; }
    }

    public  DateTimeProvider()
    {

        _date = new DateTime();
    }
    public string ToShortDateString()
    {
        return _date.ToShortDateString();
    }
}

然后我在我的主单元中使用它并想使用属性注入但我遇到了一些问题,这是我所拥有的快照:

public class Atm : IAtm
{
   public ITimeProvider _timeProvider { get;set; }
}

这不起作用,因为我没有指定类型。我可以这样做

public ITimeProvider<DateTime> _timeProvider { get;set; }

但是我将无法使用其他时间提供程序。我也考虑过(并且是我能想出的唯一解决方案)是使 ATM 通用,所以像这样

 public class Atm<T> : IAtm
 {
      public ITimeProvider<T> _timeProvider { get;set; }
 }

但是我觉得我不能使用属性注入,有没有其他方法可以做到这一点,以便我能够测试它?

【问题讨论】:

  • “但我遇到了一些问题”。 “不起作用,因为我没有指定类型”,但是您已经使用我假设的注入容器注册了接口的实现?
  • “但那样我就不能使用另一个 timeprovider” – 您考虑使用与 DateTime 不同的类型来表示日期和次?
  • 不是,但我确实想模拟它以进行测试
  • 您只需要能够模拟DateTime.Now 进行测试(您与那个时间提供者一起使用)。没有理由封装整个DateTime 类型;您可以按照您需要的方式创建日期时间对象以进行测试。
  • @Sumsar1812 - 你能解释一下为什么你需要DateTime 作为一个泛型类型参数吗?

标签: c# unit-testing datetime


【解决方案1】:

您要抽象的是 DateTime.Now 函数而不是 DateTime 数据类型,您可以保持实现完全相同,但只需修复类型。

public interface ITimeProvider
{
    DateTime Now { get; }
    string ToShortDateString();
}

public class DateTimeProvider : ITimeProvider
{

    public DateTime Now
    {
        get { return DateTime.Now; }
    }

    public string ToShortDateString()
    {
        return Now.ToShortDateString();
    }
}


public class RemoteTimeProvider : ITimeProvider
{
    public DateTime Now
    {
        get 
        { 
            using(var client = new WebClient())
            {
                var timeString = client.DownloadString(http://www.timeapi.org/utc/now);
                return DateTime.Parse(timeString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime()
            }

        }
    }

    public  DateTimeProvider()
    {

    }
    public string ToShortDateString()
    {
        //ToDo
    }
}

另外,我真的不明白你的ToShortDateString() 做了什么,它不接受参数,它只是使用从new DateTime() 返回的值。

【讨论】:

    【解决方案2】:

    使用Fakes 能够对系统或其他组件进行单元测试, 在您的控制之下。

    [TestClass]
    public class TestClass1
    { 
            [TestMethod]
            public void TestCurrentYear()
            {
                int fixedYear = 2000;
    
                // Shims can be used only in a ShimsContext:
                using (ShimsContext.Create())
                {
                    // Arrange:
                    // Shim DateTime.Now to return a fixed date:
                    System.Fakes.ShimDateTime.NowGet = 
                    () =>
                    { return new DateTime(fixedYear, 1, 1); };
    
                    // Instantiate the component under test:
                    var componentUnderTest = new MyComponent();
    
                    // Act:
                    int year = componentUnderTest.GetTheCurrentYear();
    
                    // Assert: 
                    // This will always be true if the component is working:
                    Assert.AreEqual(fixedYear, year);
                }
            }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 2011-09-30
      • 2017-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多