【问题标题】:Comparing lists of objects with double property with FluentAssertions (C#)使用 FluentAssertions (C#) 比较具有双重属性的对象列表
【发布时间】:2017-12-27 19:12:03
【问题描述】:

我正在尝试将两个对象列表与 FluentAssertions 进行比较。对象具有存储为双精度的属性,该属性可能有少量偏差。有没有一种有效的方法可以在不遍历列表的情况下做到这一点?我目前的方法看起来像

actualList.ShouldAllBeEquivalentTo(expectedList, options => options.Excluding(o => o.DoubleProperty));

for (var i = 0; i < actualList.Count; i++)
{
    actualList[i].DoubleProperty
                 .Should().BeApproximately(expectedList[i].DoubleProperty, precision);
}

随着这个问题不断出现,这有点难看和烦人。另一种可能性(受Fluent Assertions: Compare two numeric collections approximately 启发)是

actualList.Select(o => o.DoubleProperty)
          .Should().Equal(expectedList.Select(o => o.DoubleProperty),
                          (left, right) => AreEqualApproximately(left, right, precision));

我会自己编写AreEqualApproximately 函数。如果可能,我想在不定义自己的辅助方法或按索引遍历列表的情况下进行比较。

【问题讨论】:

  • 它有什么难看的?我的意思是,除了没有换行符序列来分解点链之外?
  • @hoodaticus 在 C# 中,我真的不应该按索引遍历列表。代码之美是您真正需要感受的东西。
  • 您需要将源数据转换为 ValueTuples 列表,其中第一项是实际列表成员,第二项是相应的预期列表成员。然后你就可以做一个 List>.ForEach(i => i.Item1.DoubleProperty .Should().BeApproximately(i.Item2.DoubleProperty,precision));当前形式的代码需要按索引进行循环的原因是因为它必须手动关联两个单独的列表。把它们放在同一个列表中,你就很好了。
  • 如果你回答我会接受。

标签: c# list unit-testing precision fluent-assertions


【解决方案1】:

使用ShouldAllBeEquivalentTo中的可用选项,以下内容也应该可以工作

actualList.ShouldAllBeEquivalentTo(expectedList, options => options
    .Using<double>(ctx => ctx.Subject.Should()
                             .BeApproximately(ctx.Expectation, precision))
    .When(o => o.SelectedMemberPath == "DoubleProperty"));

【讨论】:

    【解决方案2】:

    您可以创建扩展方法,将您的实际值和预期值合并到一个列表中并在它们上进行 foreach:

    public static class ExtensionMethods
    {
        public static IEnumerable<ValueTuple<T, T>> Merge<T>(this List<T> a, List<T> b)
        {
            for (int x = 0, y = 0; x < a.Count && y < a.Count; x++, y++) 
            {
                yield return ValueTuple.Create(a[x], b[y]);
            }
        }
    
        public static void ForEach<T>(this IEnumerable<T> s, Action<T> m)
        {
           foreach (var i in s) m(i);
        }
    }
    

    然后,你可以这样使用它:

    actualList.Merge(expectedList)
       .ForEach(i => 
       i.Item1.DoubleProperty
       .Should().BeApproximately(i.Item2.DoubleProperty, precision)); 
    

    【讨论】:

      【解决方案3】:

      基于Fluent Assertions: Approximately compare a classes properties

      actualList.ShouldAllBeEquivalentTo(
          expectedList,
          options => options.Using<double>(d => d.Subject.Should().BeApproximately(d.Expectation, precision))
                            .WhenTypeIs<double>()
      

      结果证明对我来说效果最好,虽然因为我必须多次这样做,但我最终在 TestInitialize 中全局更改了 FluentAssertions 的选项。

      【讨论】:

        猜你喜欢
        • 2013-06-08
        • 2021-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-15
        • 1970-01-01
        • 2021-01-11
        • 1970-01-01
        相关资源
        最近更新 更多