You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 08:24:52