如何在 FluentAssertions 中对集合中的属性使用排除



我有两个类:

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"));

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

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

这可能吗?

怎么样?

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改变了一些事情。

我的对象包含其他对象的字典。字典中的对象包含我要排除的其他对象。我遇到的场景是围绕测试 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))
  );

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

这由 FluentAssertions 6.7 支持

actualA.Should().BeEquivalentTo(expectedA, options =>
    options
       .For(a => a.Children)
       .Exclude(b => b.ID));

简单的方法是直接在集合上设置断言,并结合对等效断言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"));

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

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

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

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

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

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

与丹尼斯答案的区别:通过苏。选定成员路径,双反斜杠以转义方括号。

actual.Should().BeEquivalentTo(expected,
  assertionOptions => assertionOptions
    .Excluding(x => x.CreationTimestamp))

但是,如果您使用结构和类覆盖等于,那么您应该更改默认值与 ComparingByMembers 比较https://fluentassertions.com/objectgraphs/#value-types

actual.Should().BeEquivalentTo(expected,
  assertionOptions => assertionOptions
    .Excluding(x => x.CreationTimestamp)
    .ComparingByMembers<T>())

最简单的方法是:

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

语法是这样的

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

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

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))

相关内容

  • 没有找到相关文章

最新更新