在xunit.net中有一个简单的方法来比较两个集合而不考虑项目的顺序吗?

在我的一个测试中,我想确保集合中有某些项目。 因此,我想将此集合与预期集合的项目进行比较,而不是关于项目的顺序 。 目前,我的测试代码看起来有点像这样:

[Fact] public void SomeTest() { // Do something in Arrange and Act phase to obtain a collection List actual = ... // Now the important stuff in the Assert phase var expected = new List { 42, 87, 30 }; Assert.Equal(expected.Count, actual.Count); foreach (var item in actual) Assert.True(expected.Contains(item)); } 

在xunit.net中有没有更简单的方法来实现这一目标? 我不能使用Assert.Equal因为此方法检查两个集合中项目的顺序是否相同。 我看了一下Assert.Collection但是没有删除上面代码中的Assert.Equal(expected.Count, actual.Count)语句。

提前感谢您的回答。

来自xunit.net的Brad Wilson告诉我,在这个Github问题中 ,应该使用LINQ的OrderBy运算符,然后使用Assert.Equal来validation两个集合包含相同的项而不考虑它们的顺序。 当然,您必须在相应的项目类上拥有一个属性,您可以在第一个位置使用它(在我的情况下我没有真正拥有)。

就个人而言,我通过使用FluentAssertions解决了这个问题, FluentAssertions是一个提供大量断言方法的库,可以以流畅的方式应用。 当然, 还有很多方法可用于validation集合 。

在我的问题的上下文中,我将使用类似下面的代码:

 [Fact] public void Foo() { var first = new[] { 1, 2, 3 }; var second = new[] { 3, 2, 1 }; first.Should().BeEquivalentTo(second); } 

此测试通过,因为BeEquivalentTo调用忽略项的顺序。

如果您不想使用FluentAssertions ,也应该是一个很好的选择。

不是Xunit,而是Linq的答案:

 bool areSame = !expected.Except(actual).Any() && expected.Count == actual.Count; 

所以在XUnit中:

 Assert.True(!expected.Except(actual).Any() && expected.Count == actual.Count)); 

正如@ robi-y所说,在Microsoft.VisualStudio.QualityTools.UnitTestFramework有CollectionAssert.AreEquivalent

也许另一种方式是:

 Assert.True(expected.SequenceEqual(actual)); 

这确实也会检查订单。 这是内部发生的事情:

 using (IEnumerator e1 = first.GetEnumerator()) using (IEnumerator e2 = second.GetEnumerator()) { while (e1.MoveNext()) { if (!(e2.MoveNext() && comparer.Equals(e1.Current, e2.Current))) return false; } if (e2.MoveNext()) return false; } return true; 

因此,如果您不关心订单,请先订购两个清单

 Assert.True(expected.OrderBy(i => i).SequenceEqual(actual.OrderBy(i => i))); 

您可以使用Microsoft的 CollectionAssert.AreEquivalent

 CollectionAssert.AreEquivalent(expected, actual);