首页
/ FluentAssertions中接口类型字段的默认等价性比较行为解析

FluentAssertions中接口类型字段的默认等价性比较行为解析

2025-06-18 07:32:49作者:田桥桑Industrious

背景介绍

在使用FluentAssertions进行单元测试断言时,开发人员可能会遇到一个不太直观的行为:当比较两个包含接口类型字段的记录或类时,默认情况下BeEquivalentToNotBeEquivalentTo方法只会比较接口中定义的成员,而忽略实现类中的其他属性。

问题现象

考虑以下测试场景:我们有一个接口ISomething和一个实现该接口的TestClass类,后者包含一个MyField属性。当比较两个包含不同MyField值的TestParent记录实例时,使用NotBeEquivalentTo断言会意外通过,尽管它们的属性值明显不同。

public class TestClass : ISomething
{
    public required string MyField { get; init; }
}

public record TestParent(ISomething Something);

[Test]
public void TestEquivalency()
{
    var first = new TestParent(new TestClass { MyField = "biscuits" });
    var second = new TestParent(new TestClass { MyField = "donkeys" });
    
    first.Should().NotBeEquivalentTo(second); // 这个断言会意外通过
}

设计原理

FluentAssertions的这种行为是经过深思熟虑的设计决策。默认情况下,它基于编译时类型(即接口类型)进行比较,而不是运行时类型(即实际实现类)。这种设计有以下考虑:

  1. 封装性原则:从接口使用者的角度看,它只关心接口契约定义的行为,不关心具体实现的内部细节。

  2. 稳定性:如果具体实现类添加了新属性,不会意外导致现有测试失败。

  3. 一致性:与C#语言本身的类型系统行为保持一致,编译时类型决定了可访问的成员。

解决方案

虽然默认行为可能不符合某些场景的需求,但FluentAssertions提供了灵活的配置选项:

  1. 临时解决方案:在特定断言中启用运行时类型比较
first.Should().NotBeEquivalentTo(second, o => o.RespectingRuntimeTypes());
  1. 全局配置:修改默认的等价性比较行为
AssertionOptions.AssertEquivalencyUsing(o => o.RespectingRuntimeTypes());

最佳实践建议

  1. 在测试涉及接口和实现类的场景时,明确考虑你真正想要比较的是什么。

  2. 如果测试的是接口契约,保持默认行为是合理的。

  3. 如果测试需要验证具体实现类的完整状态,应该显式地使用RespectingRuntimeTypes选项。

  4. 对于重要的测试场景,考虑添加注释说明为什么选择特定的比较策略,以提高代码可维护性。

总结

FluentAssertions的这一设计虽然初次接触时可能令人困惑,但它体现了良好的软件工程原则。理解这一行为背后的设计理念,能帮助开发人员更有效地使用这个强大的测试工具。在需要比较实现类完整状态时,记住使用RespectingRuntimeTypes选项即可获得期望的行为。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
openHiTLS-examplesopenHiTLS-examples
本仓将为广大高校开发者提供开源实践和创新开发平台,收集和展示openHiTLS示例代码及创新应用,欢迎大家投稿,让全世界看到您的精巧密码实现设计,也让更多人通过您的优秀成果,理解、喜爱上密码技术。
C
52
461
kernelkernel
deepin linux kernel
C
22
5
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
349
381
nop-entropynop-entropy
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
7
0
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
131
185
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
873
517
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
336
1.09 K
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
179
264
cherry-studiocherry-studio
🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端
TypeScript
607
59
note-gennote-gen
一款跨平台的 Markdown AI 笔记软件,致力于使用 AI 建立记录和写作的桥梁。
TSX
83
4