FluentAssertions - 当属性属于不同类型时,应该()。BeEquivalentTo()

时间:2018-03-01 16:14:51

标签: c# unit-testing fluent-assertions

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

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:来自subject的预期成员Id是System.Guid,但找到了System.String。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

以下两种方法可以将对象与具有相同名称的不同类型成员进行比较。

第一种方法是在名为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