对比集合时如何在错误信息中展示标识字段(主键)
单元测试优化:自定义对象集合对比的错误信息显示
在单元测试中对比包含标识属性(主键)的复杂对象集合时,当前错误信息仅显示集合索引(如actual[1].Prop2),无法直接定位到具体是哪个对象(通过主键MyKey)出了问题。示例错误信息如下:
Expected property actual[1].Prop2 to be the same string, but they differ at index 0:
↓ (actual)
"invalidValue"
"expectedValue"
↑ (expected).
希望能在错误信息中展示类似MyKey = "value1"的标识属性内容,方便快速定位问题。相关代码如下:
class Foo { public string MyKey { get; set; } public string Prop2 { get; set; } } [Fact] public void Test() { var expected = new[] { new Foo { MyKey = "value0", Prop2 = "expectedValue" }, new Foo { MyKey = "value1", Prop2 = "expectedValue" }, }; var actual = new[] { new Foo { MyKey = "value0", Prop2 = "expectedValue" }, new Foo { MyKey = "value1", Prop2 = "invalidValue" }, }; actual.Should().BeEquivalentTo(expected, options => { // 原代码中Prop1不存在,属于笔误 // ctx.Subject.Prop1.Should().Be(ctx.Expectation.Prop1); return options; }); }
优化方案(基于FluentAssertions)
要让错误信息显示对象的标识属性,需从对象匹配逻辑和错误信息格式化两方面配置:
- 按主键匹配对象(可选)
如果集合不需要严格按顺序对比,可指定用MyKey作为匹配依据,避免因顺序不同导致的错误匹配:
options.ByMember(m => m.MyKey);
如果需要保持顺序对比,使用:
options.WithStrictOrdering();
- 自定义错误信息中的对象标识
通过配置等价性步骤,自定义Foo对象的显示名称,让错误信息直接展示MyKey的值:
options.ConfigureEquivalencyStepForType<Foo>(step => step.FormatSubject(ctx => $"Foo(MyKey = \"{ctx.Subject.MyKey}\")"));
也可针对单个属性对比时自定义错误消息,明确关联对应的MyKey:
options.Using<string>(ctx => { ctx.Subject.Should().Be(ctx.Expectation, $"Foo的MyKey为\"{ctx.ParentContext.Subject.MyKey}\"时,{ctx.Path}属性不匹配"); }).WhenTypeIs<string>();
修改后的完整测试代码
class Foo { public string MyKey { get; set; } public string Prop2 { get; set; } } [Fact] public void Test() { var expected = new[] { new Foo { MyKey = "value0", Prop2 = "expectedValue" }, new Foo { MyKey = "value1", Prop2 = "expectedValue" }, }; var actual = new[] { new Foo { MyKey = "value0", Prop2 = "expectedValue" }, new Foo { MyKey = "value1", Prop2 = "invalidValue" }, }; actual.Should().BeEquivalentTo(expected, options => { // 按MyKey匹配对象(若不需要顺序可启用) // options.ByMember(m => m.MyKey); // 保持顺序对比 options.WithStrictOrdering(); // 自定义Foo对象的显示格式 options.ConfigureEquivalencyStepForType<Foo>(step => step.FormatSubject(ctx => $"Foo(MyKey = \"{ctx.Subject.MyKey}\")")); return options; }); }
优化后的错误信息示例
Expected property Foo(MyKey = "value1").Prop2 to be the same string, but they differ at index 0:
↓ (actual)
"invalidValue"
"expectedValue"
↑ (expected).
这样就能直接通过错误信息定位到具体是MyKey=value1的对象出了问题,无需再通过索引反推。
内容的提问来源于stack exchange,提问作者Liero
相关产品推荐
相关产品推荐

