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

时间:2015-01-29 15:10:24

标签: 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));
}

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

提前感谢您的回答。

6 个答案:

答案 0 :(得分:21)

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

就个人而言,我通过使用FluentAssertions解决了这个问题,there are also a lot of methods that you can use to validate collections是一个提供大量断言方法的库,可以以流畅的方式应用。当然,Shouldly

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

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

    first.Should().BeEquivalentTo(second);
}

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

如果您不想使用FluentAssertions,

http://hpics.li/9fc4863也是一个不错的选择。

答案 1 :(得分:11)

不是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

答案 2 :(得分:6)

也许另一种方式是:

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

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

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;

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

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

答案 3 :(得分:1)

You can use CollectionAssert.AreEquivalent from Microsoft

CollectionAssert.AreEquivalent(expected, actual);

答案 4 :(得分:1)

如果您集合中的项目保证是唯一的,您可以使用 HashSet。这是因为 HashSet 本质上是无序的。

[Fact]
public void Foo()
{
    var expected = new HashSet<int> { 1, 2 ,3 };
    var actual = new HashSet<int> { 3, 2, 1 };

    Assert.Equal(expected, actual);
}

这是可行的,因为 xUnit 使用 ISet.SetEquals() 方法。

<块引用>

此方法忽略元素的顺序以及其他中的任何重复元素。

如果 actual 集合只是一个常规集合(不是 HashSet),那么您仍然可以自己使用 SetEquals(),但您必须意识到重复项将被忽略。

[Fact]
public void Foo()
{
    var expected = new HashSet<int> { 1, 2 ,3 };
    var actual = new [] { 3, 2, 1, 1, 1 };

    // This also passes, but may not be what you want
    Assert.True(expected.SetEquals(actual));
}

答案 5 :(得分:0)

这几乎与您的代码相同。唯一的简化是使用from django_seed import Seed seeder = Seed.seeder() from myapp.models import Game, Player seeder.add_entity(Game, 5) seeder.add_entity(Player, 10) inserted_pks = seeder.execute() 而不是spark-defaults.conf

spark.master.rest.enabled true