FluentAssertions:如何在每对元素上使用自定义比较来比较两个集合? [英] FluentAssertions: How to compare two collections using a custom comparison on each pair of elements?

查看:0
本文介绍了FluentAssertions:如何在每对元素上使用自定义比较来比较两个集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下输入:

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方法来进行此断言?

推荐答案

改进断言的一种方法是将比较提取到自定义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,请通过在BeEquivalentToEquivalencyAssertionOptions config参数上调用Using(new CustomerEmployeeComparer())来添加它。

注意:由于您的示例要求按顺序比较这两个列表,因此我已将WithStrictOrdering()添加到下面的示例中。

[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; }
}

将第一个Employee的名称更改为Jonathan,现在会显示以下失败消息:

Message: Expected item[0] to be "Jonathan" with a length of 8, but "John" has a length of 4, differs near "hn" (index 2).

With configuration:
- Use declared types and members
- Compare enums by value
- Include all non-private properties
- Include all non-private fields
- Match member by name (or throw)
- Without automatic conversion.
- UnitTestProject15.CustomerEmployeeComparer
- Without automatic conversion.
- Always be strict about the collection order

对于任何感兴趣的人来说,有一个相关的未决问题,即覆盖要比较的属性。 https://github.com/fluentassertions/fluentassertions/issues/535

这篇关于FluentAssertions:如何在每对元素上使用自定义比较来比较两个集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆