如何用Fluent Assertions正确编写这些测试断言?
问题解答
当前LINQ方式是否不合适?
不算绝对不合适,但确实没有充分发挥Fluent Assertions(FA)的特性优势。用LINQ提前过滤、投影数据后再断言,会把测试逻辑拆成“数据预处理”和“断言验证”两个独立部分,而FA的设计初衷是让断言逻辑更连贯、表达性更强,直接针对原始集合做验证,既能提升代码可读性,还能在断言失败时保留更完整的上下文信息,输出更精准的错误提示。
符合FA理念的写法实现
1. 验证GroupName恰好包含4个不同值
直接针对原始集合构建链式断言,无需提前用LINQ提取数据:
var expectedGroups = new[] { "Audio Advanced #1", "Audio Advanced #2", "Movie Versions", "Unwanted" }; result.Should() // 确保所有元素的GroupName都属于预期集合 .OnlyContain(item => expectedGroups.Contains(item.GroupName)) .And // 提取GroupName去重后验证数量与预期一致 .Select(item => item.GroupName) .Distinct() .HaveCount(expectedGroups.Length);
也可以同时验证去重后的具体值:
result.Should() .Select(item => item.GroupName) .Distinct() .HaveCount(4) .And.BeEquivalentTo(expectedGroups);
2. 验证指定分组下的CfName和CfAnchor匹配指定列表
无需提前用Where过滤,直接用FA的内置断言能力定位目标元素并验证:
// 定义预期的分组元素(利用record的特性直接创建实例) var expectedAudioItems = new[] { new CustomFormatGroupItem("Audio Advanced #1", "TrueHD ATMOS", "truehd-atmos"), new CustomFormatGroupItem("Audio Advanced #1", "DTS X", "dts-x"), new CustomFormatGroupItem("Audio Advanced #1", "ATMOS (undefined)", "atmos-undefined"), new CustomFormatGroupItem("Audio Advanced #1", "DD+ ATMOS", "dd-atmos"), new CustomFormatGroupItem("Audio Advanced #1", "TrueHD", "truehd"), new CustomFormatGroupItem("Audio Advanced #1", "DTS-HD MA", "dts-hd-ma"), new CustomFormatGroupItem("Audio Advanced #1", "DD+", "ddplus"), new CustomFormatGroupItem("Audio Advanced #1", "DTS-ES", "dts-es"), new CustomFormatGroupItem("Audio Advanced #1", "DTS", "dts") }; result.Should() .Contain(expectedAudioItems, options => options // 因为已经限定分组名,可排除该属性重复验证 .Excluding(item => item.GroupName) // 如果需要严格匹配元素顺序,加上此配置(默认忽略顺序) .WithStrictOrdering() );
如果不想重复创建CustomFormatGroupItem实例,也可以用匿名类型配合断言:
result.Should() .Where(item => item.GroupName == "Audio Advanced #1") .BeEquivalentTo(new[] { new { CfName = "TrueHD ATMOS", CfAnchor = "truehd-atmos" }, new { CfName = "DTS X", CfAnchor = "dts-x" }, new { CfName = "ATMOS (undefined)", CfAnchor = "atmos-undefined" }, new { CfName = "DD+ ATMOS", CfAnchor = "dd-atmos" }, new { CfName = "TrueHD", CfAnchor = "truehd" }, new { CfName = "DTS-HD MA", CfAnchor = "dts-hd-ma" }, new { CfName = "DD+", CfAnchor = "ddplus" }, new { CfName = "DTS-ES", CfAnchor = "dts-es" }, new { CfName = "DTS", CfAnchor = "dts" } }, options => options.ExcludingMissingMembers());
总结
Fluent Assertions并没有完全禁止使用LINQ预处理数据,只是更推荐直接针对原始集合构建链式断言,让测试逻辑的意图更清晰。如果场景中元素数量较多,用Where配合BeEquivalentTo依然是简洁易读的合理方案,核心是尽量让断言逻辑连贯、上下文完整。
内容的提问来源于stack exchange,提问作者void.pointer
相关产品推荐
相关产品推荐

