我有两个类:
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))