C# 在xunit.net中是否有一种简单的方法可以比较两个集合,而不考虑项目';点菜?

C# 在xunit.net中是否有一种简单的方法可以比较两个集合,而不考虑项目';点菜?,c#,automated-tests,xunit.net,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 Asser

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

[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));
}
[事实]
公共测试()
{
//在“安排和行动”阶段做一些事情以获得集合
列出实际值=。。。
//现在是断言阶段的重要内容
var expected=新列表{42,87,30};
Assert.Equal(预期的.Count,实际的.Count);
foreach(实际中的var项目)
True(应为.Contains(item));
}

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

不是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中,有一种方法可能是:

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;

xunit.net的Brad Wilson在这篇文章中告诉我,应该使用LINQ的
OrderBy
操作符,然后使用
Assert.Equal
来验证两个集合是否包含相同的项,而不考虑它们的顺序。当然,您必须在相应的item类上有一个属性,您可以首先使用该属性进行排序(在我的例子中,我没有这个属性)

就我个人而言,我通过使用一个库解决了这个问题,该库提供了许多可以流畅地应用的断言方法。当然

在我的问题中,我将使用类似于以下代码的代码:

[事实]
公共图书馆
{
var first=new[]{1,2,3};
var second=new[]{3,2,1};
第一个.Should().beequivalento(第二个);
}
此测试通过,因为
beequivalento
调用忽略了项目的顺序


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

您可以使用


这与您的代码几乎相同。唯一的简化是使用
Assert.Contains
而不是
Assert.True(预期的.Contains(…)

[事实]
公共测试()
{
//在“安排和行动”阶段做一些事情以获得集合
列出实际值=。。。
//现在是断言阶段的重要内容
var expected=新列表{42,87,30};
Assert.Equal(预期的.Count,实际的.Count);
foreach(预期中的var项目)
Assert.Contains(项目,实际);
}

我认为你是对的@aquinas:Raph的答案将失败,如果列表1是{1,3,5},而列表2是{1,3,3,5}。现在我想起来了,检查大小可能还不够,因为如果列表1是{1,1,3,5,5},而列表2是{1,3,3,5,5},那么检查大小可能会失败。尽管如此,+1表示一个非常优雅的起点。除了产生两个列表之间的差异。如果一个列表中有多个项目,则将生成此项目。因此,无需检查尺寸。Hmmm。是的,如果值重叠,则失败。此外,该测试不按顺序检查值。你必须在计数时加上支票。所以我更正了我的回答谢谢你的回答Raph。它是有效的,但它不是我想要的。重要的是,如果测试失败,它只会在错误消息中声明“condition is not true”,这不会解释预期集合中哪些元素不在实际集合中(反之亦然)。这应该包含在抛出的异常消息中,否则我必须调试测试以获取此信息。因此,我将创建自己的Assert方法,并尝试将其贡献给xunit.net。您也可以使用from mstest…谢谢您-也许我应该在回答中指定实际列表不一定包含int值。实际上,我使用的值不能排序(即,相应的类不实现
IComparable
)。因此,
SequenceEqual
不是一个选项,因为它检查项目的顺序。如果类上有一个identity属性,也许可以使用它按此属性排序。在最坏的情况下,可以为类实现自定义IEqualityComparer。
Assert.True(expected.OrderBy(i => i).SequenceEqual(actual.OrderBy(i => i)));
CollectionAssert.AreEquivalent(expected, actual);