FluentAssertions Should().BeEquivalentTo() 失败,列表包含从相同接口派生的运行时指定类型

Posted

技术标签:

【中文标题】FluentAssertions Should().BeEquivalentTo() 失败,列表包含从相同接口派生的运行时指定类型【英文标题】:FluentAssertions Should().BeEquivalentTo() fails with Lists containing run-time specified types deriving from identical interface 【发布时间】:2019-01-21 15:07:57 【问题描述】:

我有以下测试说明了我试图实现的一个简单示例(两个等效列表的比较):

[Fact]
public void Test()

    // Arrange
    var list1 = new List<IDomainEvent>  new BusinessCreatedDomainEvent  Name = "Microsoft"  ;
    var list2 = new List<IDomainEvent>  new BusinessCreatedDomainEvent  Name = "Microsoft"  ;

    // Act

    // Assert
    list1.Should().BeEquivalentTo(list2);

理想情况下,每个列表应该能够包含任意数量的源自IDomainEvent 接口的不同类型的项目。测试当前失败。我怀疑这与 Should().BeEquivalentTo 不适合比较运行时指定的类型有关。如何配置此示例,以便测试通过?

目前测试结果为:

[8/14/2018 5:21:26 PM Error] [xUnit.net 00:00:00.7909767]     BusinessWrite.UnitTests.Infrastructure.EventStoreUnitTests.Test [FAIL]
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.7922005]       System.InvalidOperationException : No members were found for comparison. Please specify some members to include in the comparison or choose a more meaningful assertion.
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.7932461]       Stack Trace:
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.7941986]         C:\projects\fluentassertions-vf06b\Src\FluentAssertions\Equivalency\GenericEnumerableEquivalencyStep.cs(74,0): at FluentAssertions.Equivalency.GenericEnumerableEquivalencyStep.Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.7945426]         C:\projects\fluentassertions-vf06b\Src\FluentAssertions\Equivalency\EquivalencyValidator.cs(85,0): at FluentAssertions.Equivalency.EquivalencyValidator.AssertEqualityUsing(IEquivalencyValidationContext context)
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.7946187]         C:\projects\fluentassertions-vf06b\Src\FluentAssertions\Equivalency\EquivalencyValidator.cs(38,0): at FluentAssertions.Equivalency.EquivalencyValidator.AssertEquality(EquivalencyValidationContext context)
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.7946610]         C:\projects\fluentassertions-vf06b\Src\FluentAssertions\Collections\CollectionAssertions.cs(394,0): at FluentAssertions.Collections.CollectionAssertions`2.BeEquivalentTo[TExpectation](IEnumerable`1 expectation, Func`2 config, String because, Object[] becauseArgs)
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.7947629]         C:\projects\fluentassertions-vf06b\Src\FluentAssertions\Collections\CollectionAssertions.cs(331,0): at FluentAssertions.Collections.CollectionAssertions`2.BeEquivalentTo[TExpectation](IEnumerable`1 expectation, String because, Object[] becauseArgs)
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.7948569]         C:\Users\Christian\source\repos\unify\src\Services\Business\BusinessWrite\BusinessWrite.UnitTests\Infrastructure\EventStoreUnitTests.cs(43,0): at BusinessWrite.UnitTests.Infrastructure.EventStoreUnitTests.Test()
[8/14/2018 5:21:26 PM Informational] [xUnit.net 00:00:00.8058517]   Finished:    BusinessWrite.UnitTests

【问题讨论】:

BusinessCreatedDomainEvent 是否覆盖等于等? 我来到这个页面只是意识到我使用了错误的方法来比较 2 个列表。我需要改用list1.Should().Equal(list2)。把它留在这里以防其他人有同样的问题 【参考方案1】:

我怀疑接口IDomainEvent 没有任何public 属性。 这解释了您看到的异常,因为BeEquivalentTo() 中的逻辑使用IDomainEvent 上的属性,因为列表的类型为List&lt;IDomainEvent&gt;

要使用 BusinessCreatedDomainEvent 上的属性来比较两个列表,您可以改为使用

list1.Should().BeEquivalentTo(list2, options => options.RespectingRuntimeTypes());

来自documentation

默认情况下,在递归比较期间选择要处理的成员时,Fluent Assertions 尊重对象或成员声明的(编译时)类型。也就是说,如果主体是 OrderDto,但分配给它的变量具有 Dto 类型,则在将对象与 order 变量进行比较时,只会考虑后一个类定义的成员。可以配置此行为,如果您愿意,可以选择使用运行时类型:

【讨论】:

以上是关于FluentAssertions Should().BeEquivalentTo() 失败,列表包含从相同接口派生的运行时指定类型的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中混合 MockVerify 和 FluentAssertions.Should()

FluentAssertions Should.Equal 在集合上,包含空值

FluentAssertions Should().BeOfType() 还是派生类型?

如何在 FluentAssertions 中使用“Which”?

FluentAssertions Should().BeEquivalentTo() 失败,列表包含从相同接口派生的运行时指定类型

当类型是 C# 9 记录时,FluentAssertions Should().BeEquivalentTo() 在微不足道的情况下失败,似乎将对象视为字符串