FluentAssertions: Как сравнить две коллекции, используя пользовательское сравнение для каждой пары элементов? - PullRequest
0 голосов
/ 28 апреля 2019

Учитывая следующие входные данные:

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();
}

Конечно, это не легко прочитать и предоставить диагностические результаты обычного качества ТВС. Есть ли какой-нибудь встроенный метод FluentAssertions, чтобы сделать это утверждение?

1 Ответ

2 голосов
/ 29 апреля 2019

Один из способов улучшить утверждение состоит в том, чтобы извлечь сравнение в пользовательский IEquivalencyStep для определения порядка сравнения Customer и Employee.

Itсостоят из двух частей:

  • 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()) для параметра EquivalencyAssertionOptions config в BeEquivalentTo.

Примечание. В качестве примера требуется сравнение двух списков по порядку.Я добавил 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 на Джонатана, теперь выдает это сообщение об ошибке:

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

...