Как в FluentAssertions сравнить два разных класса с совпадениями по полям?
Допустим есть два не всязанных наследованием класса. У них есть несколько совподающих полей (в примере ниже это поля field_1 и field_2)
class A
{
int field_1;
int field_2;
int field_3;
}
class B
{
int field_1;
int field_2;
int field_4;
}
A a = new A {field_1 = 1, field_2 = 2, field_3 = 3}
B b = new B {field_1 = 1, field_2 = 2, field_4 = 4}
Можно ли написать нечто подобное a.Should().BeEquivalentTo(b); и получить положительный результат?
Ответы (1 шт):
Можно перегрузить метод Equals. В паре с ним всегда следует перегружать метод GetHashCode. Они были любезно сгенерированы Студией автоматически, после чего я подправил метод Equals, чтобы происходило сравнение не только с объектом своего типа, но и другого.
public class A
{
public int field_1;
public int field_2;
public int field_3;
public override bool Equals(object obj)
{
if (obj is A a)
{
return field_1 == a.field_1
&& field_2 == a.field_2
&& field_3 == a.field_3;
}
else if (obj is B b)
{
return field_1 == b.field_1
&& field_2 == b.field_2;
}
return false;
}
public override int GetHashCode()
{
int hashCode = -1805700735;
hashCode = hashCode * -1521134295 + field_1.GetHashCode();
hashCode = hashCode * -1521134295 + field_2.GetHashCode();
return hashCode;
}
}
public class B
{
public int field_1;
public int field_2;
public int field_4;
public override bool Equals(object obj)
{
if (obj is B b)
{
return field_1 == b.field_1
&& field_2 == b.field_2
&& field_4 == b.field_4;
}
else if (obj is A a)
{
return field_1 == a.field_1
&& field_2 == a.field_2;
}
return false;
}
public override int GetHashCode()
{
int hashCode = -1805700735;
hashCode = hashCode * -1521134295 + field_1.GetHashCode();
hashCode = hashCode * -1521134295 + field_2.GetHashCode();
return hashCode;
}
}
Этот способ полезен не только для модульного тестирования, но и для сравнения объектов в реальном коде.
Если сравниваемые типы нельзя/нежелательно менять, то можно обойтись возможностями FluentAsserions:
a.Should().BeEquivalentTo(b, options => options.ExcludingMissingMembers());
По умолчанию BeEquivalentTo сравнивает все члены объектов. Но можно исключить из сравнения отсутствующие.
Или, наоборот, можно указать только те свойства/поля, которые должны участвовать в сравнении:
a.Should().BeEquivalentTo(b, options => options
.Including(x => x.field_1).Including(x => x.field_2));
Документация: Object graph comparison