FluentAssertions:排序列表的等价性

64

我正在尝试使用C#中的FluentAssertions建立两个列表的等价性,其中有两个重要问题:

  1. 元素是通过它们所持有的值进行比较而不是通过引用进行比较(即它们是等价的,而不是相等的)
  2. 列表中元素的顺序很重要

在FluentAssertions(甚至是NUnit)中没有可以做到这一点的函数吗?

谢谢!

8个回答

116

默认情况下,ShouldBeEquivalentTo() 会忽略集合中的顺序,因为在大多数情况下,如果两个集合包含相同的项但顺序不同,它们仍然是等效的。如果您关心顺序,请在 options => 参数上使用 WithStrictOrdering() 的其中一个重载。

示例:

var myList = Enumerable.Range(1, 5);
var expected = new[]
{
    1, 2, 3, 4, 5
};

//succeeds
myList.ShouldBeEquivalentTo(expected, options => options.WithStrictOrdering());

//fails
myList.Reverse().ShouldBeEquivalentTo(expected, options => options.WithStrictOrdering());

文档中阅读更多有关这些选项的信息。


3
太完美了,正是我所期望的。感谢您向我介绍“options参数”! :) - Samuel Neugber
13
жҲ‘иҠұдәҶеӨӘй•ҝж—¶й—ҙжүҚж„ҸиҜҶеҲ°Should().BeEquivalentTo()е’ҢShouldBeEquivalentTo()并дёҚзӣёеҗҢ... - RJB
1
我将在5.0版本中修复此问题。请访问https://github.com/fluentassertions/fluentassertions/pull/593了解详情。 - Dennis Doomen
为什么NotBeEquivalentTo没有带选项的重载?我需要验证两个可枚举对象是否相等,但顺序不同。 - Toby

21

虽然我晚了,但我使用的是Fluent Assertions版本:

actualRows.Should().BeEquivalentTo(expectedRows,options => options.WithStrictOrdering());

它会检查所有属性的值是否相等,使用这个选项时,顺序很重要。如果顺序不重要,则省略options参数,它将确保来自一个集合的项在另一个集合中存在某个位置。 希望对某人有所帮助。


3
使用最新的fluentassertions nuget,您需要按以下方式使用它:actualRows.Should().BeEquivalentTo(expectedRows,options => options.WithStrictOrdering()); - thomasgalliker

6

我认为你可以这样做:

myObject.List.SequenceEqual(myOtherObject.ListToCompare).Should().BeTrue();

只有当使用Object.Equal(element1, element2)时列表中的元素相等时,此方法才有效。

如果不是这种情况,则需要为列表中的对象实现自己的EqualityComparer,然后使用:

myObject.List.SequenceEqual(myOtherObject.ListToCompare, myEqualityComparer)
             .Should().BeTrue();

我认为这已经非常整洁了。谢谢! - Samuel Neugber

4

这篇文章中得知。

FA 2.0引入的新方法ShouldBeEquivalentTo()进行了深度结构比较并报告任何区别。

您可以按照以下方式实现。

actual.Should().BeEquivalentTo(expectation, c => c.WithStrictOrdering());

1
只是注意到可以将FluentAssertions配置为默认使用此选项:https://fluentassertions.com/tips/#using-global-assertionoptions - Frank Schwieterman

1

在我的类似任务中,我发现了下一个方法:

IEnumerable collection = new[] { 1, 2, 5, 8 };

collection
    .Should()
    .ContainInOrder(new[] { 1, 5, 8 });

集合断言文档


1

对于这个问题的第2部分,检查集合中元素的顺序,截至2020年(不确定是哪个版本引入了此功能,目前使用的是v5.10.3),您可以使用:

mySimpleCollection.Should().BeInDescendingOrder()myComplexCollection.Should().BeInDescendingOrder(x => x.SomeProperty)

或者

mySimpleCollection.Should().BeInAscendingOrder()myComplexCollection.Should().BeInAscendingOrder(x => x.SomeProperty)

或者

mySimpleCollection.Should().NotBeInAscendingOrder()myComplexCollection.Should().NotBeInAscendingOrder(x => x.SomeProperty)

或者

mySimpleCollection.Should().NotBeInDescendingOrder()myComplexCollection.Should().NotBeInDescendingOrder(x => x.SomeProperty)


1
你需要使用ShouldAllBeEquivalentTo方法,它应该比较列表中两个对象图的属性值。
*编辑:我可能会使用Linq Sequence equal和一个自定义的相等比较器,该比较器使用ShouldBeEquivalentTo来关心元素的顺序。

已经尝试过了,不关心元素的顺序。编辑 -> 我也是这么想的,只是希望我在某个地方忽略了一个函数。 - Samuel Neugber
也许可以尝试使用SequenceEqual和自定义的相等比较器。 - gmn

0

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