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

时间:2019-09-19 14:53:57

标签: c# asp.net fluent-assertions

我的代码中有几个类,这些类由XSD生成器工具根据XSD文件定义自动生成。这些类看起来很相似,但名称相似,但是基于XSD架构(我们已经从外部供应商那里收到),生成的类都是不同的类型。这些是非常复杂的类,具有许多深层嵌套的属性和枚举值。因此,我们过去常常直接使用类,因为很难采用通用的方法来使用类。

但是我接受了挑战,并且我成功了。为了避免在使用这些类时出现代码重复,我使用XSD生成的文件外部的接口定义为类添加了属性,以防止再次生成类时利用诸如以下的部分类声明来覆盖它们:

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生成的文件之外实现接口的简化示例

class1.Should().BeEquivalentTo(expectedClass);

在这个简化的示例中,此构造使我可以使用接口而不是具体的实现来处理标头和正文属性,因为我们拥有数十个结构相同但类型不同的类,而无需进行编辑XSD工具的自动生成的代码。这一切都很好,很花哨。

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

  1. 公共xsdGeneratedClass1Header标头{设置}
  2. 公共xsdGeneratedClass1Body身体{get;组; }
  3. 公共IXsdGeneratedClassHeader头文件{组; }
  4. 公共IXsdGeneratedClassBody正文{get;组; }

我要比较的对象是带有接口类型的header和body属性,因为这些将是其中唯一包含实际数据的对象。具体的类属性始终都是null。所以我做了这样的测试:

{{1}}

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

我尝试使用RespectingRuntimeTypes选项,该选项使测试通过,但随后看来它没有像应有的那样比较对象。例如,如果我更改了ExpectedClass的header属性中的一个属性值,例如我知道它与class1中的值不匹配,则测试仍会通过。

我已经尝试搜寻互连网以寻找答案,并且在搜索过程中我已经走到了尽头,基本上我正在思考是应该编写自己的工具还是做出大量的手动断言。欧比旺断言,请帮忙!

1 个答案:

答案 0 :(得分:0)

非常感谢Jonas Nyrup!似乎是一个缺陷,现在已在Fluent断言的主分支中进行了修订。同时,有人在github线程中发布了一个解决方法的答案,这也对我有用。很高兴。谢谢!

在某个地方声明此类,可在单元测试中使用

public class ReflectionMemberMatchingRule : IMemberMatchingRule
{
    public SelectedMemberInfo Match(SelectedMemberInfo expectedMember, object subject, string memberPath, IEquivalencyAssertionOptions config) => expectedMember;
}

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

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

现在可以正常工作了!