222

How can this test fail?

[TestMethod]
public void Get_Code()
{
    var expected = new List<int>();
    expected.AddRange(new [] { 100, 400, 200, 900, 2300, 1900 });

    var actual = new List<int>();
    actual.AddRange(new [] { 100, 400, 200, 900, 2300, 1900 });

    Assert.AreEqual(expected, actual);
    // Assert.AreSame(expected, actual)       fails
    // Assert.IsTrue(expected.Equals(actual)) fails
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
Ray Cheng
  • 12,230
  • 14
  • 74
  • 137

7 Answers7

451

To make assertions about collections, you should use CollectionAssert:

CollectionAssert.AreEqual(expected, actual);

List<T> doesn't override Equals, so if Assert.AreEqual just calls Equals, it will end up using reference equality.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 9
    I wish this gave more detailed messages when it failed. "Different number of elements" and "Element at index 0 do not match" are slightly useless. *What are they then?!* – Colonel Panic May 15 '15 at 15:45
  • 49
    If you don't care about item order: {A,B,C} == {C,B,A}, then use `CollectionAssert.AreEquivalent` instead https://msdn.microsoft.com/en-us/library/ms243779.aspx – user2023861 Aug 11 '16 at 20:25
  • 3
    Note that `CollectionAssert.AreEqual` can be noticeably slower than `Assert.IsTrue...SequenceEqual` – Mark Sowul Oct 17 '16 at 16:04
  • 2
    @MarkSowul: But it comes with much better failure diagnostics, right? – Jon Skeet Oct 17 '16 at 16:28
  • 1
    It's so slow I'd rather do `if (!SequenceEqual) { CollectionAssert.AreEqual }` – Mark Sowul Oct 17 '16 at 20:38
  • 3
    @MarkSowul: Hmm... sounds like that's worth reporting as a bug then. No reason it should be that bad. – Jon Skeet Oct 17 '16 at 20:40
  • We were using it to compare byte arrays (`MemoryStream.ToArray()`) -- 50-150 ms for `SequenceEqual`, 500ms - 1s for `CollectionAssert.AreEqual`. Probably for smaller collections it's a negligible difference but presumably it doesn't scale well. – Mark Sowul Oct 17 '16 at 20:45
  • 1
    I was using Assert.AreEqual and couldn't find the issue. – DanielV Dec 21 '16 at 16:26
  • If an argument does not implement `ICollection` (e.g., because it is of type `IList`), use `actual.ToList()` to make it an `ICollection`. – Florian Winter May 11 '20 at 11:58
46

I guess this will help

Assert.IsTrue(expected.SequenceEqual(actual));
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • 4
    That was my fall-back too, but I'd hope that CollectionAssert would provide more helpful failure messages. – Jon Skeet Jun 15 '12 at 17:48
  • 4
    Sadly, it doesn't really: "CollectionAssert.AreEqual failed. (Element at index 0 do not match.)" (what are the elements?) – namey Jun 04 '16 at 12:13
  • Second that, twice as fast as CollectionAsser.AreEqual for my byte array with 300k elements – juwens Jun 15 '21 at 22:46
23

If you want to check that each contains the same collection of values then you should use:

CollectionAssert.AreEquivalent(expected, actual);

Edit:

"Two collections are equivalent if they have the same elements in the same quantity, but in any order. Elements are equal if their values are equal, not if they refer to the same object." - https://msdn.microsoft.com/en-us/library/ms243779.aspx

topham101
  • 239
  • 2
  • 4
19

I tried the other answers in this thread, and they didn't work for me and I was comparing collections of objects that had the same values stored in their properties, but the objects were different.

Method Call :

CompareIEnumerable(to, emailDeserialized.ToIndividual,
            (x, y) => x.ToName == y.ToName && x.ToEmailAddress == y.ToEmailAddress);

Method for comparisons:

private static void CompareIEnumerable<T>(IEnumerable<T> one, IEnumerable<T> two, Func<T, T, bool> comparisonFunction)
    {
        var oneArray = one as T[] ?? one.ToArray();
        var twoArray = two as T[] ?? two.ToArray();

        if (oneArray.Length != twoArray.Length)
        {
            Assert.Fail("Collections are not same length");
        }

        for (int i = 0; i < oneArray.Length; i++)
        {
            var isEqual = comparisonFunction(oneArray[i], twoArray[i]);
            Assert.IsTrue(isEqual);
        }
    }
Declan
  • 1,850
  • 1
  • 18
  • 23
7

this test compares a date input, checks if its a leap year, if so, outputs 20 leap years from the inputted date, if not, outputs the NEXT 20 leap years, myTest.Testing refers to the myTest instance which in turn calls the values from a List called Testing containing the calculated values required. part of an exercise I had to do.

[TestMethod]
        public void TestMethod1()
        {
            int testVal = 2012;
            TestClass myTest = new TestClass();
            var expected = new List<int>();
            expected.Add(2012);
            expected.Add(2016);
            expected.Add(2020);
            expected.Add(2024);
            expected.Add(2028);
            expected.Add(2032);
            expected.Add(2036);
            expected.Add(2040);
            expected.Add(2044);
            expected.Add(2048);
            expected.Add(2052);
            expected.Add(2056);
            expected.Add(2060);
            expected.Add(2064);
            expected.Add(2068);
            expected.Add(2072);
            expected.Add(2076);
            expected.Add(2080);
            expected.Add(2084);
            expected.Add(2088);
            var actual = myTest.Testing(2012);
            CollectionAssert.AreEqual(expected, actual);
        }
5

Fluent assertions does deep comparisons of arrays actualArray.Should().BeEquivalentTo(expectedArray)

Ram Pratap
  • 1,079
  • 11
  • 8
  • None of the other answers worked for me, though I could see via debug my lists were equal. A variation on this answer worked: actual.ShouldDeepEqual(expected); – MJ Hughes Jul 21 '23 at 14:19
0
List<AdminUser> adminDetailsExpected = new List<AdminUser>()
{
new AdminUser  {firstName = "test1" , lastName = "test1" , userId = 
"001test1"  },
new AdminUser {firstName = "test2" , lastName = "test2" , userId = 
"002test2"   }
};

//Act

List<AdminUser> adminDetailsActual = RetrieveAdmin(); // your retrieve logic goes here

//Assert

Assert.AreEqual(adminDetailsExpected.Count, adminDetailsActual.Count);  //Test succeeds if the count matches else fails. This count can be used as a work around to test
karthik kasubha
  • 392
  • 2
  • 13