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

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:预期成员ID为{ff73e7c7-21f0-4f45-85fa-f26cd1ecafd0},但发现“ {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:期望主题的成员ID为System.Guid,但找到了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")));


第二种方法使用https://stackoverflow.com/a/47947052/1087627中的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

07-24 19:06
查看更多