FluentAssertions - Should().BeEquivalentTo() 当属性属于不同类型时

FluentAssertions - Should().BeEquivalentTo() when properties are of different type

如何比较 属性 名称相同但类型不同的对象?

public class A
{
    public Guid Id { get; set; }
}

public class B
{
    public string Id { get; set; }
}

public static B Map(A a){
    return new B { Id = a.Id.ToString() };
}

版本 1:

void Main()
{
    A a = new A { Id = Guid.NewGuid() };
    B b = Map(a);

    b.Should().BeEquivalentTo(a);
}

这会产生以下错误:

AssertionFailedException: Expected member Id to be {ff73e7c7-21f0-4f45-85fa-f26cd1ecafd0}, but found "{ff73e7c7-21f0-4f45-85fa-f26cd1ecafd0}".

文档表明可以使用 Equivalence Comparison Behavior

自定义 属性 断言规则

版本 2:

void Main()
{
    A a = new A { Id = Guid.NewGuid() };
    B b = Map(a);

    b.Should().BeEquivalentTo(a, 
        options => options
            .Using<Guid>(ctx => ctx.Subject.Should().Be(ctx.Expectation))
            .WhenTypeIs<Guid>());
}

但如果属性不是同一类型,它会产生 运行 次异常。

AssertionFailedException: Expected member Id from subject to be a System.Guid, but found a System.String.

有什么想法吗?

这里有两种方法可以比较具有不同类型的同名成员的对象。

第一种方法是指定名为 Id

的成员之间的等效性
A expected = new A { Id = Guid.NewGuid() };
B actual = Map(expected);

actual.Should().BeEquivalentTo(expected,
    options => options
    .Using<object>(ctx => ctx.Subject.Should().Be(ctx.Expectation.ToString()))
    .When(info => info.SelectedMemberPath.EndsWith("Id")));

第二种方法使用 中的 DifferentObjectsEquivalencyStep 和您自己的 Map 函数。 然后它将 A 的实例转换为 B,现在很容易比较。

AssertionOptions.AssertEquivalencyUsing(c => 
    c.Using(new DifferentObjectsEquivalencyStep<A, B>(Map)));

A expected = new A { Id = Guid.NewGuid() };
B actual = Map(expected);

actual.Should().BeEquivalentTo(expected);

有一个关于它的开放issue