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

Fluent Assertions 6 不同成员类型名称的集合比较方案问询

Fluent Assertions 6+ 异成员集合等价比较方案

Fluent Assertions 6之后官方已经简化了这类成员类型、名称不匹配的集合等价比较逻辑,不需要再自行实现IEquivalencyStep接口,以下是三种常用的可行方案:

方案1:单次断言配置映射规则

适合仅单次需要比较的场景,直接在断言语句中指定成员对应关系即可:
假设你需要比较的两个集合的元素类型定义如下:

// 源集合元素类型
public class SourceItem
{
    public int Id { get; set; }
    public string SourceName { get; set; }
    public DateTime CreateTime { get; set; }
}

// 目标集合元素类型
public class TargetItem
{
    public long ItemId { get; set; }
    public string TargetName { get; set; }
    public long CreateTimestamp { get; set; }
}

断言写法:

List<SourceItem> sourceList = GetSourceList();
List<TargetItem> targetList = GetTargetList();

sourceList.Should().BeEquivalentTo(targetList, options => options
    // 映射Id和ItemId(自动兼容int和long的类型差异)
    .For<SourceItem>(src => src.Compare(x => x.Id).To<TargetItem>(tgt => tgt.ItemId))
    // 映射SourceName和TargetName
    .For<SourceItem>(src => src.Compare(x => x.SourceName).To<TargetItem>(tgt => tgt.TargetName))
    // 自定义时间和时间戳的转换逻辑
    .For<SourceItem>(src => src.Compare(x => x.CreateTime).To<TargetItem>(tgt => 
        DateTimeOffset.FromUnixTimeMilliseconds(tgt.CreateTimestamp).DateTime
    ))
);

方案2:全局注册类型映射规则

如果多处测试都需要用到同一组类型的比较规则,可以全局注册映射,避免重复写配置:

// 全局测试初始化时执行一次即可
AssertionOptions.DefaultEquivalencyPlan.Add<SourceItem, TargetItem>(map => map
    .Map(src => src.Id, tgt => tgt.ItemId)
    .Map(src => src.SourceName, tgt => tgt.TargetName)
    .Map(src => src.CreateTime, tgt => DateTimeOffset.FromUnixTimeMilliseconds(tgt.CreateTimestamp).DateTime)
);

后续断言时不需要再额外配置:

sourceList.Should().BeEquivalentTo(targetList);

方案3:自定义比较委托处理复杂场景

如果成员对应逻辑非常复杂,用配置方式难以实现,可以直接指定自定义比较逻辑:

sourceList.Should().BeEquivalentTo(targetList, options => options
    .Using<object>(ctx =>
    {
        var source = ctx.Subject as SourceItem;
        var target = ctx.Expectation as TargetItem;
        // 这里可以写任意自定义比较逻辑
        source.Id.Should().Be((int)target.ItemId);
        source.SourceName.Should().Be(target.TargetName);
        source.CreateTime.Should().BeCloseTo(
            DateTimeOffset.FromUnixTimeMilliseconds(target.CreateTimestamp).DateTime, 
            TimeSpan.FromSeconds(1)
        );
    })
    .When((subject, expectation) => subject is SourceItem && expectation is TargetItem)
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 12:36:03