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

如何用FluentAssertions测试Enumerable是否包含自身的‘子集’

优雅的FluentAssertions子集断言写法

需求场景

需要验证一个集合(actual)是否包含另一个集合(expected)作为属性子集:即预期集合的每个元素,都能在实际集合中找到对应的元素(实际元素可以包含更多属性,但指定的属性必须完全匹配)。示例测试代码如下:

[Fact]
public void Test1()
{
    // Arrange
    var expected = new[]
    {
        new {F1 = 1, F2 = "1" },
        new {F1 = 2, F2 = "2" },
    };

    // Act
    var actual = new[]
    {
        new {F1 = 1, F2 = "1", F3 = true },
        new {F1 = 2, F2 = "2", F3 = true },
        new {F1 = 3, F2 = "3", F3 = true },
    };

    // Assert
    // 需要优雅的FluentAssertions表达式
}

失败的尝试

直接使用BeEquivalentTo并配置ExcludingMissingMembers会因为集合元素数量不匹配报错:

// Assert
actual
    .Should()
    .BeEquivalentTo(expected, o => o.ExcludingMissingMembers());

错误提示:

Expected actual to be a collection with 2 item(s), but {{ F1 = 1, F2 = 1, F3 = True }, { F1 = 2, F2 = 2, F3 = True }, { F1 = 3, F2 = 3, F3 = True }} contains 1 item(s) more than {{ F1 = 1, F2 = 1 }, { F1 = 2, F2 = 2 }}.

可行但不够优雅的写法

以下写法可以实现需求,但可读性和流畅性不足:

  1. 先过滤实际集合再做等价比较:
actual
    .Where(a => expected.Any(e => e.F1 == a.F1 && e.F2 == a.F2))
    .Should()
    .BeEquivalentTo(expected, o => o.ExcludingMissingMembers());
  1. 遍历预期集合逐个断言:
expected
    .ToList()
    .ForEach(expectedItem =>
        actual
            .Should()
            .ContainEquivalentOf(
                expectation: expectedItem, 
                config: o => o.ExcludingMissingMembers())
    );

// 或者普通foreach写法
foreach (var expectedItem in expected)
{
    actual
        .Should()
        .ContainEquivalentOf(
            expectation: expectedItem,
            config: o => o.ExcludingMissingMembers());
}

优雅的解决方案

使用FluentAssertions提供的AllSatisfy方法,结合ContainEquivalentOf实现流畅且可读的断言:

// Assert
expected.Should().AllSatisfy(expectedItem =>
    actual.Should().ContainEquivalentOf(expectedItem, o => o.ExcludingMissingMembers()),
    because: "expected is a 'subset' of actual");

说明

  • AllSatisfy:验证预期集合中的每个元素都满足后续断言逻辑,完全符合FluentAssertions的流畅风格;
  • ContainEquivalentOf:检查实际集合中存在与预期元素属性匹配的项,ExcludingMissingMembers配置允许实际元素包含更多未在预期中定义的属性;
  • 通过because参数添加断言失败时的提示信息,能大幅提升调试效率。

内容的提问来源于stack exchange,提问作者dani herrera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:50:42