如何在 FluentAssertions 中为集合中的属性使用排除?
Posted
技术标签:
【中文标题】如何在 FluentAssertions 中为集合中的属性使用排除?【英文标题】:How to use Exclude in FluentAssertions for property in collection? 【发布时间】: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] 索引器,断言将失败。
这可能吗?
【问题讨论】:
【参考方案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 选项以使用当前版本 - 请参阅 ***.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) );
【讨论】:
以上是关于如何在 FluentAssertions 中为集合中的属性使用排除?的主要内容,如果未能解决你的问题,请参考以下文章
FluentAssertions:如何在每对元素上使用自定义比较来比较两个集合?
FluentAssertions:如何指定该集合应包含一定数量的匹配谓词的元素?
FluentAssertions:如何指定该集合应包含一定数量的匹配谓词的元素?