如何在FluentAssertions中使用Exclude来获取集合中的属性?

时间:2014-03-03 09:09:35

标签: c# unit-testing fluent-assertions

我有两个班级:

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]索引器,则断言失败。

这可能吗?

8 个答案:

答案 0 :(得分:32)

怎么样?

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

或者你可以在属性路径上进行RegEx匹配,例如

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

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

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

答案 1 :(得分:20)

我刚遇到类似的问题,最新版本的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))
  );

花了一些时间来研究如何做到这一点,但这确实很有用!

答案 2 :(得分:8)

简单的方法是直接在集合上设置断言,并将其排除在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"));

答案 3 :(得分:2)

基于Dennis Doomen‘s answer的RegEx匹配提示,我能够使其发挥作用

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

与丹尼斯答案的区别:传递su.SelectedMemberPath,双反斜杠以逃避方括号。

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

我认为语法类似于

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

答案 6 :(得分:0)

最简单的方法是:

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

答案 7 :(得分:0)

您可以在其中传递表达式列表的扩展类

c1 <- c()
for (t in 1:t) {
  for (s in 1:s) {
    for (j in 1:4) {
      for (i in 1:2){
        c1 <- cbind(c1, c(t,s,j,i,function(j,t,s,i)))
      }
    }
  }
}

用法

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;
    }
}
相关问题