Fluent Assertions 6.0 升级指南:关键变更与技术解析

Fluent Assertions 6.0 升级指南:关键变更与技术解析

fluentassertions A very extensive set of extension methods that allow you to more naturally specify the expected outcome of a TDD or BDD-style unit tests. Targets .NET Framework 4.7, as well as .NET Core 2.1, .NET Core 3.0, .NET 6, .NET Standard 2.0 and 2.1. Supports the unit test frameworks MSTest2, NUnit3, XUnit2, MSpec, and NSpec3. fluentassertions 项目地址: https://gitcode.com/gh_mirrors/fl/fluentassertions

前言

Fluent Assertions 6.0 版本带来了一系列重要的架构改进和功能优化,同时也包含了一些必要的破坏性变更。本文将从技术角度深入解析这些变更,帮助开发者顺利升级到新版本。

枚举断言的重构

在 5.x 版本中,枚举断言由 ObjectAssertions 类处理,这种设计存在几个明显问题:

  1. 许多通用断言方法(如 BeNull)对枚举类型没有实际意义
  2. 枚举专用方法 HaveFlag 却对所有引用类型都可见
  3. 类型安全性不足,允许不同枚举类型间的错误比较

新版改进

6.0 版本引入了专门的 EnumAssertionsNullableEnumAssertions 类,提供了更精确的类型安全断言:

// 6.0 正确用法
MyEnum.One.Should().Be(MyEnum.One); // 编译通过
MyEnum.One.Should().Be(1);         // 编译错误

新增的专用方法:

  • HaveSameValueAs:比较底层数值
  • HaveSameNameAs:比较枚举名称
  • HaveValue:验证特定数值

等效性比较改进

对象图比较中的枚举处理更加严格:

// 5.x 可以通过的断言,6.0 将失败
var subject = new { Value = "One" };
var expectation = new { Value = MyOtherEnum.One };
subject.Should().BeEquivalentTo(expectation);

必须明确指定比较方式:

subject.Should().BeEquivalentTo(expectation, opt => opt.ComparingEnumsByName());

等效性验证架构改进

6.0 对 IEquivalencyStep 进行了重大重构:

  1. 将验证上下文中的主体和期望值分离到新的 Comparands 类型
  2. 移除了 CanHandle 方法
  3. Handle 的布尔返回值改为更明确的 EquivalencyResult 枚举

新的基类 EquivalencyStep<T> 简化了自定义步骤的实现。

Using 方法的类型安全增强

5.x 版本中 Using<TProperty>WhenTypeIs<TMemberType> 之间缺乏类型约束,可能导致运行时错误。6.0 增加了编译时类型检查:

// 5.x 编译通过但运行时失败
.Using<int>(e => ...).WhenTypeIs<string>()

// 6.0 直接编译错误

同时修复了可空值类型的处理问题,确保 null0 不再被错误地等同。

值格式化器性能优化

IValueFormatter 接口进行了重构以提高大型对象图的格式化性能:

  1. 不再返回字符串,而是使用 FormattedObjectGraph 构建输出
  2. 支持更精细的格式化控制
  3. 改进深度限制处理

示例格式化器实现:

public void Format(object value, FormattedObjectGraph graph, FormattingContext context)
{
    string result = "\"" + value + "\"";
    if (context.UseLineBreaks)
        graph.AddFragmentOnNewLine(result);
    else
        graph.AddFragment(result);
}

集合断言改进

6.0 移除了对非泛型集合的支持:

IEnumerable subject;
subject.Should().HaveCount(42); // 不再编译
subject.Cast<object>().Should().HaveCount(42); // 正确用法

同时移除了 BeEquivalentTo(params object[]) 重载,以保持类型一致性。

异步异常断言

6.0 完全拥抱异步编程模型,不再自动同步阻塞异步代码:

// 5.x 可用但不推荐
asyncMethod.Should().Throw<Exception>();

// 6.0 正确用法
await asyncMethod.Should().ThrowAsync<Exception>();

这一变更避免了潜在的同步上下文死锁问题。

事件断言链式调用变更

事件约束方法(如 WithArgs)现在只返回匹配的事件,改变了链式调用行为:

// 5.x 方式(6.0不再工作)
foo.ShouldRaise("Event")
   .WithArgs<string>(x => x == "a")
   .WithArgs<string>(x => x == "b");

// 6.0 正确方式
foo.ShouldRaise("Event").WithArgs<string>(x => x == "a");
foo.ShouldRaise("Event").WithArgs<string>(x => x == "b");

升级建议

  1. 首先解决编译错误,特别是枚举和集合相关的断言
  2. 检查异步测试代码,替换为 *Async 版本
  3. 审查事件断言链式调用
  4. 如有自定义格式化器或等效性步骤,按新接口更新实现

这些变更虽然带来了一些升级成本,但显著提高了类型安全性、性能和使用体验,是向更健壮测试代码迈进的重要一步。

fluentassertions A very extensive set of extension methods that allow you to more naturally specify the expected outcome of a TDD or BDD-style unit tests. Targets .NET Framework 4.7, as well as .NET Core 2.1, .NET Core 3.0, .NET 6, .NET Standard 2.0 and 2.1. Supports the unit test frameworks MSTest2, NUnit3, XUnit2, MSpec, and NSpec3. fluentassertions 项目地址: https://gitcode.com/gh_mirrors/fl/fluentassertions

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

任凝俭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值