FluentAssertions - 比较包含名称相似但类型不同的属性的对象

Posted

技术标签:

【中文标题】FluentAssertions - 比较包含名称相似但类型不同的属性的对象【英文标题】:FluentAssertions - Comparing objects containing properties with similar names but different types 【发布时间】:2020-01-20 15:39:12 【问题描述】:

我们的代码中有几个类是由 XSD 生成器工具从 XSD 文件定义中自动生成的。这些类看起来非常相似,名称相似,但基于 XSD 模式(我们从外部供应商处获得),生成的类都是不同类型的。这些都是相当复杂的类,有很多深度嵌套的属性和枚举值。因此,我们过去常常直接使用类,因为很难用一种通用的方法来处理类。

但我接受了挑战,而且我(有点)成功了。为了在使用这些类时避免代码重复,我使用 XSD 生成文件之外的接口定义向类添加了属性,以防止它们在再次生成类时被覆盖,利用部分类声明,如下所示:

XSD 生成类的简化示例

public partial class xsdGeneratedClass1

    public xsdGeneratedClass1Header header  get; set 
    public xsdGeneratedClass1Body body  get; set; 


public partial class xsdGeneratedClass2

    public xsdGeneratedClass2Header header  get; set 
    public xsdGeneratedClass2Body body  get; set; 

接口的简化示例,其中属性还包含类型接口,我们编写它以匹配 XSD 生成的类中的属性

public interface IXsdGeneratedClass

    IXsdGeneratedClassHeader header  get; set; 
    IXsdGeneratedClassBody body  get; set; 

我们在 XSD 生成的文件之外实现接口的简化示例

public partial class xsdGeneratedClass1 : IXsdGeneratedClass

    public IXsdGeneratedClassHeader header  get; set; 
    public IXsdGeneratedClassBody body  get; set; 


public partial class xsdGeneratedClass2 : IXsdGeneratedClass

    public IXsdGeneratedClassHeader header  get; set; 
    public IXsdGeneratedClassBody body  get; set; 

在这个简化的例子中,这个构造允许我使用接口而不是具体实现来处理标题和正文属性,对于我们拥有的数十个具有相同结构但具有不同类类型的类,无需在XSD 工具的自动生成代码。这一切都很好,花花公子。

当尝试使用 Fluent Assertions 比较单元测试中的对象时,问题就出现了。 Fluent Assertions 似乎很难知道要比较的实例化对象的哪些属性。在这个简单的示例中,xsdGeneratedClass1 的实例化对象将具有四个属性:

    公共 xsdGeneratedClass1Header 标头 获取;设置 public xsdGeneratedClass1Body body get;放; 公共 IXsdGeneratedClassHeader 标头 获取;放; 公共 IXsdGeneratedClassBody 正文 获取;放;

我要比较的对象是具有接口类型的 header 和 body 属性,因为它们将是唯一具有实际数据的对象。具体的类属性始终为空。所以我做了这样的测试:

class1.Should().BeEquivalentTo(expectedClass);

但 Fluent Assertions 似乎不断将 class1 的 IXsdGeneratedClassHeader 标头与 expectedClass 的 xsdGeneratedClass1Header 标头进行比较,该标头为空。

我曾尝试使用 RespectingRuntimeTypes 选项,它使测试通过,但它似乎没有按应有的方式比较对象。如果我更改了 expectedClass 标头属性中的属性值,例如我知道与 class1 中的值不匹配,则测试仍然通过。

我已经尝试在互联网上搜索答案,并且我的搜索已经结束,基本上我正在考虑是否应该编写自己的工具或进行大量手动断言。欧比旺断言,请帮忙!

【问题讨论】:

这可能是github.com/fluentassertions/fluentassertions/issues/1130 中描述的问题。还要确保BeEquivalentTo<T> 的泛型类型TIXsdGeneratedClass 谢谢。这解决了我的问题!请参阅下面的帖子:-) 【参考方案1】:

非常感谢乔纳斯·奈鲁普!似乎是一个缺陷,现在在 Fluent Assertions 的主分支中进行了修正。与此同时,有人在 github 线程中发布了一个解决方法,这也对我有用。很高兴。谢谢!

在某处声明这个类,以便在您的单元测试中使用

public class ReflectionMemberMatchingRule : IMemberMatchingRule

    public SelectedMemberInfo Match(SelectedMemberInfo expectedMember, object subject, string memberPath, IEquivalencyAssertionOptions config) => expectedMember;

通过将配置添加到 Fluent Assertions,在单元测试中使用扩展类。

AssertionOptions.AssertEquivalencyUsing(x => x.Using(new ReflectionMemberMatchingRule()));

现在可以正常工作了!

【讨论】:

以上是关于FluentAssertions - 比较包含名称相似但类型不同的属性的对象的主要内容,如果未能解决你的问题,请参考以下文章

FluentAssertions 对象图比较,包括 JSON 对象

.Net FluentAssertions .Contains 不能正确比较对象

FluentAssertions Should.Equal 在集合上,包含空值

FluentAssertions 不应该包含失败

FluentAssertions:如何在每对元素上使用自定义比较来比较两个集合?

FluentAssertions 比较列表的内容而不是列表本身