Reputation: 5281
To piggyback on this SO question...
How does this test fail?
[TestMethod]
public void DummyTest() {
var expected = new List<List<string>>() {
new List<string>(){ "123456", "25.6", "15", "a" },
new List<string>(){ "123457", "3107450.82", "1", "bcdef" },
new List<string>(){ "123458", "0.01", "900000", "-fgehk" }
};
var actual = new List<List<string>>() {
new List<string>(){ "123456", "25.6", "15", "a" },
new List<string>(){ "123457", "3107450.82", "1", "bcdef" },
new List<string>(){ "123458", "0.01", "900000", "-fgehk" }
};
CollectionAssert.AreEqual(expected, actual);
}
By the way, Assert.IsTrue(expected.SequenceEqual(actual));
also fails.
Is there a better way to test collections of collections?
Using .NET 4.6.1.
Upvotes: 2
Views: 1670
Reputation: 203802
That comparison method is going to look at the first item from each collection, check using the default comparer for that type if they're equal, and if not, consider the outer collections unequal. It'll then go on to check the other elements in the same manner.
The default equality comparer for List<string>
is going to compare the references of the two objects, not compare the underlying values of the two lists, because List
doesn't change that default behavior from object
.
You could write your own IComparer
that knows how to checks if two collections are actually equal, and provide that comparer to CollectionAssert
, if you want the items in the inner collections to be compared using the values of the items in the collection.
Upvotes: 6
Reputation: 23078
One way to implement this is using the following code:
public static bool AreEqual<T>(IList<T> list1, IList<T> list2)
{
if (list1?.Count != list2?.Count)
return false;
// order does not matter. Remove OrderBy, if it matters
// return list1.OrderBy(_ => _).SequenceEqual(list2.OrderBy(_ => _));
return list1.SequenceEqual(list2);
}
public static bool AreEqualListOfLists<T>(IList<List<T>> lists1, IList<List<T>> lists2)
{
return lists1.All(innerList1 => lists2.Any(innerList2 => AreEqual(innerList1, innerList2)));
}
static void Main(string[] args)
{
var expected = new List<List<string>>
{
new List<string> {"123456", "25.6", "15", "b"},
new List<string> {"123457", "3107450.82", "1", "bcdef"},
new List<string> {"123458", "0.01", "900000", "-fgehk"}
};
var actual = new List<List<string>>
{
new List<string> {"123456", "25.6", "15", "b"},
new List<string> {"123457", "3107450.82", "1", "bcdef"},
new List<string> {"123458", "0.01", "900000", "-fgehk"}
};
var areEqual = AreEqualListOfLists(expected, actual);
}
It is slightly longer than the SelectMany
solution, but it allows more flexibility (e.g. if order does not matter at deeper level, it can be easily adjusted or provide meaningful error message on difference).
Upvotes: 0