60

我有两节课:

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 的方法(而不是对每个元素进行排除)。

我已经阅读了这个问题,但是如果我删除 [0] 索引器,则断言失败。

这可能吗?

4

9 回答 9

57

关于什么?

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")));
于 2014-03-04T20:25:58.150 回答
34

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

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

于 2015-08-12T18:16:42.363 回答
13

简单的方法是直接在集合上设置断言,并结合其对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"));
于 2014-03-03T09:41:07.833 回答
3

基于丹尼斯·杜门(Dennis Doomen)回答的正则表达式匹配想法,我能够使其正常工作

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

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

于 2018-08-15T11:56:31.403 回答
2

ShouldBeEquivalentTo方法现在似乎已过时,为了获得接受答案的路径,您可以使用Excluding重载IMemberInfo.SelectedMemberPath代替:

expected.Should().BeEquivalentTo(actualA, options => 
    options.Excluding((IMemberInfo mi) => mi.SelectedMemberPath.EndsWith("ID")));
于 2021-01-15T14:50:56.257 回答
2

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

expectedA.ShouldBeEquivalentTo(expectedB, o => o.Excluding(s => s.Children));
expectedA.Children.ShouldBeEquivalentTo(expectedB.Children, o => o.Excluding(s => s.Id));
于 2021-12-14T11:00:51.063 回答
1

最简单的方法是:

expected.ShouldBeEquivalentTo(actual, config => config.ExcludingMissingMembers());
于 2018-05-18T06:30:30.440 回答
0

一个扩展类,您可以在其中传递表达式列表

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))
于 2020-06-03T20:48:27.247 回答
0

我认为语法类似于

       actual.Should().BeEquivalentTo(
        expected, 
        config => config.Excluding(o => o.Id).Excluding(o => o.CreateDateUtc) });
于 2021-03-23T15:20:11.563 回答