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

时间:2019-04-28 19:41:51

标签: c# unit-testing xunit assertion fluent-assertions

提供以下输入:

var customers = new[] {
    new Customer { Name = "John", Age = 42 },
    new Customer { Name = "Mary", Age = 43 }
};
var employees = new[] {
    new Employee { FirstName = "John", Age = 42 },
    new Employee { FirstName = "Mary", Age = 43 }
};

使用FluentAssertions比较这些列表的最佳方法是什么?

目前我唯一的方法是这样的-与Enumerable.SequenceEqual十分相似:

using (var customerEnumerator = customers.GetEnumerator())
using (var employeeEnumerator = employees.GetEnumerator())
{
    while (customerEnumerator.MoveNext())
    {
        employeeEnumerator.MoveNext().Should().BeTrue();
        var (customer, employee) = (customerEnumerator.Current, employee.Current);

        customer.Name.Should().BeEquivalentTo(employee.FirstName);
        customer.Age.Should().Be(employee.Age);
    }
    employeeEnumerator.MoveNext().Should().BeFalse();
}

当然,这既不容易阅读,也不提供FA常规质量的诊断输出。是否有任何FluentAssertions内置方法可以做出此断言?

1 个答案:

答案 0 :(得分:2)

改善断言的一种方法是将比较提取到自定义IEquivalencyStep中,以指导如何比较CustomerEmployee

它由两部分组成:

  • CanHandle确定何时可以进行此比较,并且
  • Handle执行自定义比较。
public class CustomerEmployeeComparer : IEquivalencyStep
{
    public bool CanHandle(IEquivalencyValidationContext context,
        IEquivalencyAssertionOptions config)
    {
        return context.Subject is Customer
            && context.Expectation is Employee;
    }

    public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator
        parent, IEquivalencyAssertionOptions config)
    {
        var customer = (Customer)context.Subject;
        var employee = (Employee)context.Expectation;

        customer.Name.Should().Be(employee.FirstName, context.Because, context.BecauseArgs);
        customer.Age.Should().Be(employee.Age, context.Because, context.BecauseArgs);

        return true;
    }
}

要在断言中使用CustomerEmployeeComparer,请在Using(new CustomerEmployeeComparer())的{​​{1}}参数上调用EquivalencyAssertionOptions config来添加它。

注意:由于您的示例需要按顺序比较两个列表,因此我在下面的示例中添加了WithStrictOrdering()

BeEquivalentTo

将第一个[TestMethod] public void CompareCustomersAndEmployeesWithCustomEquivalencyStep() { // Arrange var customers = new[] { new Customer { Name = "John", Age = 42 }, new Customer { Name = "Mary", Age = 43 } }; var employees = new[] { new Employee { FirstName = "John", Age = 42 }, new Employee { FirstName = "Mary", Age = 43 } }; // Act / Assert customers.Should().BeEquivalentTo(employees, opt => opt .Using(new CustomerEmployeeComparer()) .WithStrictOrdering()); } public class Employee { public string FirstName { get; set; } public int Age { get; set; } } public class Customer { public string Name { get; set; } public int Age { get; set; } } 的名称更改为Jonathan,现在会显示以下失败消息:

Employee

对于任何感兴趣的人,都有一个有关覆盖哪些属性进行比较的公开问题。 https://github.com/fluentassertions/fluentassertions/issues/535