FluentAssertions - 当属性类型不同时,应该使用Should().BeEquivalentTo()函数

4
如何比较具有相同名称但不同类型属性的对象?
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}"。

文档建议使用 等价比较行为 可能可以实现自定义属性断言规则。

版本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 类型。

有什么想法吗?

1个回答

11

以下是比较具有相同名称但类型不同成员对象的两种方法。

第一种方式是指定名为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://dev59.com/cqfja4cB1Zd3GeqP0Ltf#47947052DifferentObjectsEquivalencyStep和你自己的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);

有一个关于此事的开放问题


1
应该将DifferentObjectsEquivalencyStep作为扩展方法添加到FluentAssertions中! - Michal Ciechan
2
@MichalCiechan 可以随意在问题跟踪器上开一个问题。我目前正在尝试另一种方法,您将能够编写.Using<string, Guid>(ctx => ctx.Subject.Should().Be(ctx.Expectation.ToString())).When(info => info.SelectedMemberPath.EndsWith("Id")))。这应该会更加稳定和表达力强。 - Jonas Nyrup

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接