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

feO*_*O2x 18 c# automated-tests xunit.net

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

[Fact]
public void SomeTest()
{
    // Do something in Arrange and Act phase to obtain a collection
    List<int> actual = ...

    // Now the important stuff in the Assert phase
    var expected = new List<int> { 42, 87, 30 };
    Assert.Equal(expected.Count, actual.Count);
    foreach (var item in actual)
        Assert.True(expected.Contains(item));
}
Run Code Online (Sandbox Code Playgroud)

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

感谢您提前的答案.

feO*_*O2x 25

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

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

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

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

    first.Should().BeEquivalentTo(second);
}
Run Code Online (Sandbox Code Playgroud)

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

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


rdu*_*com 11

不是Xunit,而是Linq答案:

bool areSame = !expected.Except(actual).Any() && expected.Count == actual.Count;
Run Code Online (Sandbox Code Playgroud)

所以在XUnit中:

Assert.True(!expected.Except(actual).Any() && expected.Count == actual.Count));
Run Code Online (Sandbox Code Playgroud)

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

  • 您也可以使用mstest中的[CollectionAssert.AreEquivalent](https://msdn.microsoft.com/en-us/library/ms243779.aspx)... (3认同)
  • 就像我玩这个时遇到的警告一样。except 本身不会产生差异。它会过滤掉第一个列表中出现在第二个列表中的所有内容。因此,如果您预期 = {1,2,3,4,4} 且实际 = {1,2,3,4,5},则断言将错误地通过。因此(如果您不打算使用 CollectionAssert),您应该测试 except 两种方式,即 `(!expected.Except(actual).Any() &amp;&amp; !actual.Except(expected).Any())` (2认同)

rdu*_*com 6

也许另一种方式是:

Assert.True(expected.SequenceEqual(actual));
Run Code Online (Sandbox Code Playgroud)

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

using (IEnumerator<TSource> e1 = first.GetEnumerator())
using (IEnumerator<TSource> e2 = second.GetEnumerator())
{
    while (e1.MoveNext())
    {
        if (!(e2.MoveNext() && comparer.Equals(e1.Current, e2.Current))) return false;
    }
    if (e2.MoveNext()) return false;
}
return true;
Run Code Online (Sandbox Code Playgroud)

因此,如果您不关心订单,只需在以下订单中订购:

Assert.True(expected.OrderBy(i => i).SequenceEqual(actual.OrderBy(i => i)));
Run Code Online (Sandbox Code Playgroud)