【问题标题】:Fluent Assertions: Using BeCloseTo on a collection of DateTime properties流畅的断言:在 DateTime 属性的集合上使用 BeCloseTo
【发布时间】:2014-09-06 20:18:01
【问题描述】:

我正在处理许多项目,每个项目都包含一个 DateProcessed 属性(一个可为空的 DateTime),并希望断言该属性设置为当前日期。当它通过处理例程时,日期都略有不同。

我想测试所有 DateProcessed 属性是否具有相对性(100 毫秒)最近的 DateTime。

Fluent Assertions 具有 .BeCloseTo 方法,该方法非常适用于单个项目。但我想将它用于整个系列。但是在查看集合时,它不能通过 Contains() 获得。

一个简化的例子...

[TestFixture]
public class when_I_process_the_items
{
    [SetUp]
    public void context()
    {
        items = new List<DateTime?>(new [] { (DateTime?)DateTime.Now, DateTime.Now, DateTime.Now } );
    }

    public List<DateTime?> items;

    [Test]
    public void then_first_item_must_be_set_to_the_current_time()
    {
        items.First().Should().BeCloseTo(DateTime.Now, precision: 100);
    }

    [Test]
    public void then_all_items_must_be_set_to_the_current_time()
    {
        items.Should().Contain .... //Not sure? :(
    }

}

【问题讨论】:

    标签: c# unit-testing datetime nunit fluent-assertions


    【解决方案1】:

    您可以在 3.5 中通过将选项配置为 ShouldBeEquivalentTo 来执行此操作。例如:

    result.ShouldBeEquivalentTo(expected, options =>
    {
        options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
        return options;
    });
    

    或者简而言之:

    result.ShouldBeEquivalentTo(expected, options => options.Using<DateTimeOffset>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTimeOffset>());
    

    如果要全局设置,请在测试框架的夹具设置方法中实现以下内容:

    AssertionOptions.AssertEquivalencyUsing(options =>
    {
        options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
        options.Using<DateTimeOffset>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTimeOffset>();
        return options;
    });
    

    【讨论】:

      【解决方案2】:

      作为对您问题的直接回答,您可以执行items.Should().OnlyContain(i =&gt; (i - DateTime.Now) &lt; TimeSpan.FromMilliseconds(100)) 之类的操作。

      但是,依赖DateTime.Now 的单元测试是一种非常糟糕的做法。你可以做的是引入这样的东西:

      public static class SystemContext
      {
          [ThreadStatic]
          private static Func<DateTime> now;
      
          public static Func<DateTime> Now
          {
              get { return now ?? (now = () => DateTime.Now); }
              set { now = value; }
          }
      }
      

      然后不要引用DateTime.Now,而是使用SystemContext.Now() 来获取当前时间。如果你这样做,你可以像这样“设置”特定单元测试的当前时间:

      SystemContext.Now = () => 31.March(2013).At(7, 0);
      

      【讨论】:

      • 这个答案怎么可能没用?我提供了一个直接的答案以及一种从一开始就避免这种情况的方法。
      • 尽管答案消除了对问题的需要,但此答案并未回答标题中提出的问题
      • 其实我的回答直接回答了这个问题并提供了替代方案。
      【解决方案3】:

      我就是这样解决的……

      [Test]
      public void then_all_items_must_be_set_to_the_current_time()
      {
          items.Should().OnlyContain(x => DateTime.Now.Subtract(x.Value).Milliseconds <= 100);
      }
      

      但如果有人知道“开箱即用”的 Fluent Assertions 方法,请告诉我。

      【讨论】:

      • 这将确保至少一项与谓词匹配。我原来的答案仍然有效。
      猜你喜欢
      • 2012-02-18
      • 2020-03-16
      • 2014-10-21
      • 2013-09-24
      • 2010-09-23
      • 2016-10-19
      • 2018-02-03
      • 2021-11-21
      • 1970-01-01
      相关资源
      最近更新 更多