【问题标题】:How to use Exclude in FluentAssertions for property in collection?如何在 FluentAssertions 中为集合中的属性使用排除?
【发布时间】:2014-04-04 06:05:45
【问题描述】:

我有两个班级:

public class ClassA
{
  public int? ID {get; set;}
  public IEnumerable<ClassB> Children {get; set;}
}

public class ClassB
{
  public int? ID {get; set;}
  public string Name {get; set;}
}

我想使用流利的断言来与 ClassA 实例进行比较。但是我想忽略 ID(因为 ID 将在保存后分配)。

我知道我能做到:

expectedA.ShouldBeEquivalentTo(actualA, options => options.Excluding(x => x.PropertyPath == "Children[0].ID"));

我显然可以为集合中的每个 ClassB 重复。但是,我正在寻找一种排除所有 ID 的方法(而不是对每个元素进行排除)。

我已阅读 this question,但是如果我删除 [0] 索引器,断言将失败。

这可能吗?

【问题讨论】:

    标签: c# unit-testing fluent-assertions


    【解决方案1】:

    怎么样?

    expected.ShouldBeEquivalentTo(actualA, options => options.Excluding(su => 
       (su.RuntimeType == typeof(ClassB)) && (su.PropertyPath.EndsWith("Id")));`
    

    或者您可以在属性路径上进行正则表达式匹配,例如

    expected.ShouldBeEquivalentTo(actualA, options => options.Excluding(su => (Regex.IsMatch
       ("Children\[.+\]\.ID"));
    

    我其实很喜欢最后一个,但是正则表达式的东西使它有点难以阅读。也许我应该扩展ISubjectInfo 使用一种方法来匹配通配符模式的路径,以便您可以这样做:

    expected.ShouldBeEquivalentTo(actualA, options => options
      .Excluding(su => su.PathMatches("Children[*].ID")));
    

    【讨论】:

    • 我将把这个标记为答案,因为扩展方法中的正则表达式是我最终采用的方法
    • 在最新版本的 FluentAssertions 中这有什么变化?我不确定PropertyPath 是否还在
    • 我尝试了这两个选项都没有成功,但能够修复 RegEx 选项以使用当前版本 - 请参阅 stackoverflow.com/questions/22142576/… 。顺便说一下,PropertyPath 的新名称是 SelectedMemberPath
    • Regex.IsMatch(x.SelectedMemberPath, @"Children\[\d+\]\.ID")
    • FluentAssertions v6 删除了 SelectedMemberPath,这里的解决方案是: options => options.Excluding((IMemberInfo x) => x.DeclaringType == typeof(ClassB) && x.Path.EndsWith("Id") )
    【解决方案2】:

    我刚刚遇到了一个类似的问题,最新版本的 FluentAssertions 改变了一些事情。

    我的对象包含其他对象的字典。字典中的对象包含我要排除的其他对象。我的场景是围绕测试 Json 序列化而忽略某些属性。

    这对我有用:

    gotA.ShouldBeEquivalentTo(expectedB , config => 
      config
        .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Venue))
        .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Exhibit))
        .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Content))
        .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Survey))
        .Excluding(ctx => ctx.SelectedMemberInfo.MemberType == typeof(Media))
      );
    

    花了一些时间弄清楚如何做,但它真的很有用!

    【讨论】:

    • 对于它的价值,你也可以传入一个匿名对象作为自 FA 5 以来的期望,并且只包含你关心的属性。
    【解决方案3】:

    简单的方法是直接在集合上设置断言,并结合ClassA等价断言的排除:

    expectedA.ShouldBeEquivalentTo(expectedB,
       o => o.Excluding(s => s.PropertyInfo.Name == "Children"));
    expectedA.Children.ShouldBeEquivalentTo(expectedB.Children,
       o => o.Excluding(s => s.PropertyInfo.Name = "Id"));
    

    【讨论】:

    • 我认为 Propertyinfo 已经不存在了。 SelectedMemberInfo.Name 应该这样做。
    【解决方案4】:

    基于Dennis Doomen‘s answer 的正则表达式匹配想法,我能够使其工作

    expected.ShouldBeEquivalentTo(actualA, options =>
      options.Excluding(su => 
         (Regex.IsMatch(su.SelectedMemberPath, "Children\\[.+\\].ID"));
    

    与丹尼斯答案的不同之处:传递 su.SelectedMemberPath,双反斜杠以转义方括号。

    【讨论】:

      【解决方案5】:

      ShouldBeEquivalentTo 方法现在似乎已过时,为了获得accepted answer 的路径,您可以使用Excluding 重载和IMemberInfo.SelectedMemberPath

      expected.Should().BeEquivalentTo(actualA, options => 
          options.Excluding((IMemberInfo mi) => mi.SelectedMemberPath.EndsWith("ID")));
      

      【讨论】:

        【解决方案6】:

        这里有一些有效的答案,但我要添加另一个不涉及字符串类型表达式的答案。

        expectedA.ShouldBeEquivalentTo(expectedB, o => o.Excluding(s => s.Children));
        expectedA.Children.ShouldBeEquivalentTo(expectedB.Children, o => o.Excluding(s => s.Id));
        

        【讨论】:

          【解决方案7】:

          最简单的方法是:

          expected.ShouldBeEquivalentTo(actual, config => config.ExcludingMissingMembers());
          

          【讨论】:

          • OP 要求排除一些现有(非缺失)成员。
          【解决方案8】:

          一个可以传递表达式列表的扩展类

          public static class FluentAssertionsExtensions {
              public static EquivalencyAssertionOptions<T> ExcludingNextProperties<T>(
                  this EquivalencyAssertionOptions<T> options,
                  params Expression<Func<T, object>>[] expressions) {
                  foreach (var expression in expressions) {
                      options.Excluding(expression);
                  }
          
                  return options;
              }
          }
          

          用法

          actual.Should().BeEquivalentTo(expected, 
                      config => config.ExcludingNextProperties(
                          o => o.Id, 
                          o => o.CreateDateUtc))
          

          【讨论】:

            【解决方案9】:

            我认为语法类似于

                   actual.Should().BeEquivalentTo(
                    expected, 
                    config => config.Excluding(o => o.Id).Excluding(o => o.CreateDateUtc) });
            

            【讨论】:

              猜你喜欢
              • 2022-02-14
              • 2017-03-21
              • 2016-10-15
              • 2015-05-20
              • 2018-04-29
              • 1970-01-01
              • 2013-05-04
              • 2018-08-02
              • 2021-09-23
              相关资源
              最近更新 更多