xUnit:如何断言两个List<T>相等?

166

我对TDD和xUnit都很陌生,因此我想测试我的方法,大概长这样:

List<T> DeleteElements<T>(this List<T> a, List<T> b);

有没有我可以使用的断言方法?我认为像这样的东西会很好

List<int> values = new List<int>() { 1, 2, 3 };
List<int> expected = new List<int>() { 1 };
List<int> actual = values.DeleteElements(new List<int>() { 2, 3 });

Assert.Exact(expected, actual);

有类似的东西吗?

6个回答

206

2021年4月1日更新

我建议使用FluentAssertions。它具有广泛的智能感知友好的断言库,适用于许多用例,包括collections

collection.Should().Equal(1, 2, 5, 8);
collection.Should().NotEqual(8, 2, 3, 5);
collection.Should().BeEquivalentTo(8, 2, 1, 5);

原始回答

xUnit.Net识别集合,因此您只需要执行以下操作:

Assert.Equal(expected, actual); // Order is important

你可以在CollectionAsserts.cs中查看其他可用的集合断言。
对于NUnit库,集合比较方法如下:
CollectionAssert.AreEqual(IEnumerable, IEnumerable) // For sequences, order matters

并且

CollectionAssert.AreEquivalent(IEnumerable, IEnumerable) // For sets, order doesn't matter

更多细节请参考这里:CollectionAssert

MbUnit 也有类似于 NUnit 的集合断言:Assert.Collections.cs


1
源代码链接已更改为http://xunit.codeplex.com/SourceControl/changeset/view/d947e347c5c3#Samples%2fAssertExamples%2fCollectionExample.cs - Julien Roncaglia
1
评论中的新链接也坏了。 - Scott Stafford
1
项目现在已经迁移到GitHub,但我还没有在那里找到那个特定的源文件。 - MEMark
1
对于复杂对象,不要忘记需要一个Equal+GetHasCode才能使其正常工作,或者给Equal方法提供一个自定义的EqualityComparer。 - maracuja-juice
12
xUnit的Equal方法对于两个内容相同的IEnumerable返回false。 - Vladimir Kocjancic

45
在当前版本的XUnit(1.5)中,您只需使用以下代码:

Assert.Equal(expected, actual);

以上方法将对这两个列表逐个元素进行比较。我不确定该方法是否适用于任何先前版本。

25
Assert.Equal 在比较集合时的问题是,如果两个集合中元素的顺序不同,即使这些元素在两个集合中都存在,它也会失败。 - Scott Lawrence
1
@ScottA.Lawrence 列表也有顺序!使用 HashSet 会得到相同的行为吗? - johv
HashSets仍然按顺序进行比较。 - bdukes
2
似乎如果集合类型不同,即使它们都以相同的顺序包含相同的项,它也会失败。 - James White
7
但它的输出非常糟糕。它不会告诉您两个列表的区别在哪里!:( - Zordid
显示剩余5条评论

25

使用xUnit时,如果您想挑选每个元素的属性进行测试,则可以使用Assert.Collection。

Assert.Collection(elements, 
  elem1 => Assert.Equal(expect1, elem1.SomeProperty),
  elem2 => { 
     Assert.Equal(expect2, elem2.SomeProperty);
     Assert.True(elem2.TrueProperty);
  });

这会测试预期的计数并确保每个动作都得到验证。


5

最近,我在我的asp.net core 2.2应用程序中使用了xUnit 2.4.0Moq 4.10.1包。

在我的情况下,我成功地通过以下两个步骤来实现:

  1. 定义 IEqualityComparer<T> 接口的实现

  2. 将比较器实例作为第三个参数传递到 Assert.True 方法中:

    Assert.True(expected, actual, new MyEqualityComparer());

但是,还有另一种更好的方法,可以使用 FluentAssertions 包来实现相同的结果。它允许您执行以下操作:

// Assert          
expected.Should().BeEquivalentTo(actual));

有趣的是,即使我对两个列表进行排序以使它们按相同顺序排列,Assert.Equal() 总是失败。


3
你的订购有问题,BeEquivalentTo不关心顺序(这就是为什么你的测试使用BeEquivalentTo通过而不是assert.Equal无法通过的原因)。 - RagnaRock

3
在当前版本的xUnit v2.4.2中,您还可以使用以下内容:
Assert.Equivalent(expected: ..., actual: ..., strict: true);

strict 参数通过要求 expected 列表中的所有值都在 actual 列表中(意味着当 strictfalse 时,expected: [1, 2] 等同于 actual: [2, 3, 1],但当 stricttrue 时不等价)来影响此比较。


2
我刚刚发现了NotStrictEqual,它似乎可以做到这一点。

4
NotStrictEqual可能会通过测试,但如果给定两个没有任何共同元素的数组,它也会通过测试。对于这个问题来说,它并不是一个有用的断言。 - Chris Dueck

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