NUnit 中的 EqualTo() 和 EquivalentTo() 有什么区别?

14

当我有一个 Dictionary<string, int> actual,然后创建一个完全相同值的新的 Dictionary<string, int> expected

  • 调用Assert.That(actual, Is.EqualTo(expected));会使测试通过。

  • 当使用Assert.That(actual, Is.EquivalentTo(expected));时,测试不会通过。

EqualTo()EquivalentTo() 之间的区别是什么?

编辑:

当测试不通过时的异常消息如下:

Zoozle.Tests.Unit.PredictionTests.ReturnsDriversSelectedMoreThanOnceAndTheirPositions:
Expected: equivalent to < [Michael Schumacher, System.Collections.Generic.List`1[System.Int32]] >
But was:  < [Michael Schumacher, System.Collections.Generic.List`1[System.Int32]] >

我的代码看起来像这样:

[Test]
public void ReturnsDriversSelectedMoreThanOnceAndTheirPositions()
{
    //arrange
    Prediction prediction = new Prediction();

    Dictionary<string, List<int>> expected = new Dictionary<string, List<int>>()
    {
        { "Michael Schumacher", new List<int> { 1, 2 } }
    };

    //act
    var actual = prediction.CheckForDriversSelectedMoreThanOnce();

    //assert
    //Assert.That(actual, Is.EqualTo(expected));
    Assert.That(actual, Is.EquivalentTo(expected));
}

public Dictionary<string, List<int>> CheckForDriversSelectedMoreThanOnce()
{
    Dictionary<string, List<int>> expected = new Dictionary<string, List<int>>();
    expected.Add("Michael Schumacher", new List<int> { 1, 2 });

    return expected;
}

Assert.That() 抛出异常并提供详细的错误信息。请查看该信息。 - abatishchev
我不太明白你的意思。Assert.That() 会抛出异常吗?这是新的 NUnit 语法 - 我认为它与旧模型没有什么不同。除此之外,你想让我把这个放在哪里? - Garth Marenghi
1
他希望你在测试失败时将NUnit的输出添加到问题中。 - Sven
如果断言失败,它会抛出相应的异常,不是吗? - abatishchev
好的,明白了 - 代码和异常已添加。 - Garth Marenghi
2个回答

18

问题标题强制我陈述以下内容:

对于枚举,Is.EquivalentTo() 允许任何元素顺序的比较。 相反,Is.EqualTo() 考虑元素的确切顺序,就像 Enumerable.SequenceEqual() 一样。

然而,在你的情况下,元素的顺序并没有问题。这里的主要点是 Is.EqualTo() 在字典比较方面有额外的代码,如此处所述。

Is.EquivalentTo() 却不然。在你的示例中,它将使用 object.Equals() 来比较键值为 KeyValuePair<string,List<int>> 的值是否相等。因为字典值是引用类型 List<int>,所以使用引用相等性进行比较。

如果你修改示例,使得 List {1, 2} 只被实例化一次并在两个字典中使用,那么 Is.EquivalentTo() 将会成功。


5

两种方法都适用于我:

var actual = new Dictionary<string, int> { { "1", 1 }, { "2", 2 } };
var expected = new Dictionary<string, int> { { "1", 1 }, { "2", 2 } };

Assert.That(actual, Is.EqualTo(expected)); // passed
Assert.That(actual, Is.EquivalentTo(expected)); // passed

  • NUnit中的Is.EqualTo()如果两个对象都是ICollection,则使用CollectionsEqual(x,y)来迭代两个对象查找差异。我猜这相当于Enumerable.SequenceEqual(x,y)

  • Is.EquivalentTo仅支持序列,并且立即执行此操作:EquivalentTo(IEnumerable)


你说得完全正确,我的问题在于我在字典中使用了字符串作为键,而将整数存储在另一个集合——列表中作为值。正是在这一点上,EquivalentTo 抛出了异常。 - Garth Marenghi
@Garth:正如你在List <int>中指出的原因,CollectionsEqual同时迭代两个集合进行比较,并且由于值也是集合,NUnit无法正确比较它们,只能调用list1.Equals(list2)来执行引用的比较,导致失败。 - abatishchev
这个失败是针对EquivalentTo()的,对吧?因为EqualTo()似乎工作得很好 -> 当我更改列表中的值时,它可以很好地检测到某些不正确的地方。 - Garth Marenghi
@Garth:是的,我在谈论EquivalentTo()。因此,仅将其用于单层集合,而不是嵌套集合。 - abatishchev

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