NUnit comparing two lists

2019-02-16 09:28发布

OK so I'm fairly new to unit testing and everything is going well until now. I'm simplifying my problem here, but basically I have the following:

[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);
}

But the test is failing, shouldn't the test pass? what am I missing?

6条回答
2楼-- · 2019-02-16 09:30

If you can't modify a class then this example can be helpful:

[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();
}
查看更多
贼婆χ
3楼-- · 2019-02-16 09:40

If you're comparing two lists, you should use test using collection constraints.

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

Also, in your classes, you will need to override the Equals method, otherwise like gleng stated, the items in the list are still going to be compared based on reference.

Simple override example:

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

    public override bool Equals(object obj)
    {
        return this.ID == (obj as Example).ID;
    }
}
查看更多
beautiful°
4楼-- · 2019-02-16 09:40

A very simple way to get this test to work is to only create the MyOtherClass instance once. That way, when comparing the item in the two lists they will be "equal" (because they reference the same object). If you do this, CollectionAssert will work just fine.

[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);
}

If you don't this though, you'll need to implement IEquatable<MyOtherClass> in MyOtherClass or override Equals to define what makes two instances of that class the "same".

查看更多
贼婆χ
5楼-- · 2019-02-16 09:43

Try to be a bit more specific about what you are trying to achieve. Explicitly telling that you want to compare entire sequence will solve the problem. I personally wouldn't rely on NUnit fancy features for determining what you meant by says AreEqual. E.g.

Assert.IsTrue(actual.SequenceEqual(expected));
查看更多
Root(大扎)
6楼-- · 2019-02-16 09:49

I convert my comment to answer on request.

Well, this fails because AreEqual uses reference comparison. In order to make it work you need value comparison(your own custom comparison).

You can pretty much do that by implementing IEquatable interface. and keep in mind when you're implementing this interface you must override Object.Equals and Object.GetHashCode as well to get consistent results.

.Net framework supports doing this without implementing IEquatable you need IEqualityComparer that should do the trick, but nunit should have a method which takes this as a overload. Am not certain about "nunit" though.

查看更多
做自己的国王
7楼-- · 2019-02-16 09:50

From Nunit documentation:

Starting with version 2.2, special provision is also made for comparing single-dimensioned arrays. Two arrays will be treated as equal by Assert.AreEqual if they are the same length and each of the corresponding elements is equal. Note: Multi-dimensioned arrays, nested arrays (arrays of arrays) and other collection types such as ArrayList are not currently supported.

You have a list of objects ... so it's not the same as comparing 2 ints. What you should do is probably compare all the objects inside the list ... (Try converting your list to an array ... might actually work :) )


As I said (and most others as well), you'll probably need to override Equals. Here's MSDN page about how to do it (Covers Equals, == operator, and GetHashCode).

Similar with more info : [compare-equality-between-two-objects-in-nunit]
(Compare equality between two objects in NUnit)

查看更多
登录 后发表回答