4

I need to compare lists like the following in my unit tests:

var x = new List<object>() { new List<int>() };
var y = new List<object>() { new List<int>() };
CollectionAssert.AreEqual(x, y, "Expected response not the same as actual response.");

But I am always getting the exception below, how do I go about overcoming this?

[Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException] = {"CollectionAssert.AreEqual failed. Expected response not the same as actual response.(Element at index 0 do not match.)"}

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
user2890243
  • 75
  • 2
  • 8
  • Similair question here: http://stackoverflow.com/questions/5194966/mstest-collectionassert-areequivalent-failed-the-expected-collection-contains – pazcal Nov 01 '13 at 10:17

7 Answers7

3

As per the msdn document. http://msdn.microsoft.com/en-us/library/ms243736.aspx

Two collections are equal if they have the same elements in the same order and quantity. Elements are equal if their values are equal, not if they refer to the same object. The values of elements are compared using Equals by default.

Now it appears that the collections are equal. Until you take a deeper look. As per the documentation

have the same elements in the same order and quantity

From your example they dont have the same elements. They have the same type of elements, and those elements have similar signatures, however the two elements are not the same. They are completely different objects.

Run your tests using the "same elements in the same order" and see what the results are. Such as.

List<int> list = new List<int>();
var x = new List<object>() { list };
var y = new List<object>() { list };
CollectionAssert.AreEqual(x, y, "Expected response not the same as actual response.");

You will find this passes as the list the parameters parameters for CollectionAssert.AreEqual are met.

Hope this clears it up.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Nico
  • 12,493
  • 5
  • 42
  • 62
2

this is because

new List<int>().Equals(new List<int>())

returns False. The outer lists are not equal, because the inner lists are not equal.

You could try using the overload that accepts an IComparer that will treat your two empty lists as equal.

Rob
  • 4,327
  • 6
  • 29
  • 55
1

As an alternative, you could consider using the FluentAssertions Unit Test framework, which is compatible with Microsoft Unit Test.

Then your code would become:

var x = new List<object>() { new List<int>() };
var y = new List<object>() { new List<int>() };

x.ShouldBeEquivalentTo(y, "Expected response not the same as actual response.");

It would also work with this sort of thing:

var ints1 = new List<int>();
var ints2 = new List<int>();

ints1.Add(1);
ints2.Add(1);

var x = new List<object>() { ints1 };
var y = new List<object>() { ints2 };

x.ShouldBeEquivalentTo(y, "Expected response not the same as actual response.");

If you changed ints2.Add(1); to ints2.Add(2);, the unit test would then correctly fail.

Note that ShouldBeEquivalentTo() recursively descends the objects being compared, and handles collections, so even lists of lists will work with it - for example:

var ints1 = new List<int>();
var ints2 = new List<int>();

ints1.Add(1);
ints2.Add(1); // Change this to .Add(2) and the unit test fails.

var objList1 = new List<object> { ints1 };
var objList2 = new List<object> { ints2 };

var x = new List<object> { objList1 };
var y = new List<object> { objList2 };

x.ShouldBeEquivalentTo(y, "Expected response not the same as actual response.");
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
0

You compare references of two empty lists, If you need compare internal value types, you have to manual compare it(for example write List<> extension).

Sample extension.

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var x = new List<object>() { new List<int>(){1} };
        var y = new List<object>() { new List<int>(){1} };
        x.SequenceRecursiveEqual(y);

    }
}

public static class ExtenderListAssert
{
    public static void SequenceRecursiveEqual(this IList sourse, IList expected)
    {
        if (sourse.Count != expected.Count)
            Assert.Fail();
        else
        {
            for (var i = 0; i < sourse.Count; i++)
            {
                var left = sourse[i];
                var right = expected[i];
                if(left is IList && right is IList)
                {
                    (left as IList).SequenceRecursiveEqual(right as IList);
                }
                else
                {
                    Assert.AreEqual(left, right);
                }
            }
        }
    }
}
sh1ng
  • 2,808
  • 4
  • 24
  • 38
0

You should use SelectMany to extract the contents of the outer lists and then check for equality, eg:

var x = new List<object>() { new List<int>() };
var y = new List<object>() { new List<int>() };

var xItems=x.SelectMany(item=>item);
var yItems=y.SelectMany(item=>item);
CollectionAssert.AreEqual(xItems, yItems, "Expected response not the same as actual response.");

As others have noted, AreEqual uses Equals on each item to check for equality and obviously two different List instances are never equal.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
-1

You can use SequenceEqual and check returned bool for assertion

nikodz
  • 727
  • 5
  • 13
-1

Use this type :

 [TestMethod]
 public void AreEqualTest1()
 {
   List<string> countries1 = new List<string> { "Israel", "USA", "Germany" };
   List<string> countries2 = new List<string> { "Israel", "USA", "Germany" };
   // First compare count of both collections:countries1 && countries2 =>
   // if not the same  count => test failed.
   // Otherwise copmare the equality items of  both collections in order, 
  // if one of the comparison  failed => test failed
   // otherwise =>=> test passed.
   CollectionAssert.AreEqual(countries1, countries2, "Not equal, hence failed");
 }
jiten
  • 5,128
  • 4
  • 44
  • 73