35

好的,所以我对单元测试还很陌生,到目前为止一切都很顺利。我在这里简化了我的问题,但基本上我有以下内容:

[Test]
public void ListTest()
{
    var expected = new List<MyClass>();
    expected.Add(new MyOtherClass());
    var actual = new List<MyClass>();
    actual.Add(new MyOtherClass());
    Assert.AreEqual(expected,actual);
    //CollectionAssert.AreEqual(expected,actual);
}

但是测试失败了,测试不应该通过吗?我错过了什么?

4

6 回答 6

66

如果要比较两个列表,则应使用 test using collection constraints

Assert.That(actual, Is.EquivalentTo(expected));

此外,在您的类中,您将需要覆盖 Equals 方法,否则就像 gleng 所述,列表中的项目仍将根据参考进行比较。

简单的覆盖示例:

public class Example
{
    public int ID { get; set; }

    public override bool Equals(object obj)
    {
        return this.ID == (obj as Example).ID;
    }
}
于 2013-11-08T14:59:24.870 回答
14

让这个测试工作的一个非常简单的方法是只创建MyOtherClass一次实例。这样,当比较两个列表中的项目时,它们将“相等”(因为它们引用相同的对象)。如果你这样做,CollectionAssert将工作得很好。

[Test]
public void ListTest()
{
    var thing = new MyOtherClass();

    var expected = new List<MyClass>();
    expected.Add(thing);

    var actual = new List<MyClass>();
    actual.Add(thing);

    CollectionAssert.AreEqual(expected,actual);
}

但是,如果您不这样做,则需要实现IEquatable<MyOtherClass>MyOtherClass覆盖Equals以定义使该类的两个实例“相同”的原因。

于 2013-11-08T14:51:59.613 回答
10

尝试更具体地说明您要实现的目标。明确告诉您要比较整个序列将解决问题。我个人不会依赖 NUnit 的花哨功能来确定您所说的 AreEqual 的意思。例如

Assert.IsTrue(actual.SequenceEqual(expected));
于 2013-11-08T14:49:01.020 回答
9

我将我的评论转换为应要求回答。

好吧,这失败了,因为AreEqual使用了参考比较。为了使其工作,您需要进行值比较(您自己的自定义比较)。

您几乎可以通过实现IEquatable接口来做到这一点。请记住,当您实现此接口时,您必须覆盖Object.EqualsObject.GetHashCode获得一致的结果。

.Net 框架支持这样做而无需实现IEquatable您需要的IEqualityComparer应该可以解决问题,但nunit应该有一个将其作为重载的方法。不过,我不确定“nunit”。

于 2013-11-08T15:00:48.653 回答
4

从 Nunit文档

从 2.2 版开始,还为比较单维数组做出了特殊规定。如果两个数组的长度相同并且每个对应的元素都相等,则 Assert.AreEqual 将两个数组视为相等。注意:目前不支持多维数组、嵌套数组(数组的数组)和其他集合类型如 ArrayList。

你有一个对象列表......所以它与比较 2 个整数不同。您应该做的可能是比较列表中的所有对象...(尝试将您的列表转换为数组...实际上可能有效:))


正如我所说(以及大多数其他人),您可能需要覆盖 Equals。这是有关如何执行此操作的MSDN页面(涵盖 Equals、== 运算符和 GetHashCode)。

与更多信息类似:[compare-equality-between-two-objects-in-nunit]
比较 NUnit 中两个对象之间的相等性

于 2013-11-08T14:45:37.907 回答
2

如果你不能修改一个类,那么这个例子会很有帮助:

[Test]
public void Arrays_Should_Be_Equal()
{
    MyClass[] array1 = GetTestArrayOfSize(10);
    MyClass[] array2 = GetTestArrayOfSize(10);

    // DOESN'T PASS
    // Assert.That(array1, Is.EquivalentTo(array2));

    Func<MyClass, object> selector = i => new { i.Property1, i.Property2 };
    Assert.That(array1.Select(selector), Is.EquivalentTo(array2.Select(selector)));
}

private MyClass[] GetTestArrayOfSize(int count)
{
    return Enumerable.Range(1, count)
        .Select(i => new MyClass { Property1 = "Property1" + i, Property2 = "Property2" + i }).ToArray();
}
于 2015-06-09T18:15:47.753 回答