92

I have two identical byte arrays in the following segment of code:

    /// <summary>
    ///A test for Bytes
    ///</summary>
    [TestMethod()]
    public void BytesTest() {
        byte[] bytes = Encoding.UTF8.GetBytes(Properties.Resources.ExpectedPacketData);
        TransferEventArgs target = new TransferEventArgs(bytes);

        byte[] expected = Encoding.UTF8.GetBytes(Properties.Resources.ExpectedPacketValue);
        byte[] actual;
        actual = target.Bytes;

        Assert.AreEqual(expected, actual);
    }

Both arrays are identical down to the very byte. In this scenario, why would Assert.AreEqual fail?

David Anderson
  • 13,558
  • 5
  • 50
  • 76
  • 1
    As a note, if you use NUnit, value comparisons of arrays are supported since version 2.2, so `Assert.AreEqual` will work fine. – AJ Richardson Oct 25 '14 at 15:04

6 Answers6

153

Assert.Equals tests using the Equals method, which by default uses reference equality and, since they are different objects, they are not equal. You'll want to compare each byte in the array and verify that they are equal. One way to do this is convert them to something that implements ICollection and use CollectionAssert.AreEqual() instead.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 4
    An array is already an `ICollection`, of course. It's even an `IList`. It's important that your "collection equality" considers ordering (i.e. collections must be equal as sequences, not just as mathematical sets). – Jeppe Stig Nielsen Jun 03 '12 at 08:19
  • This answere is wrong! "Assert.AreEqual checks that objectOne.Equals(objectTwo) will return true." (see http://blog.robustsoftware.co.uk/2009/05/difference-between-areequal-and-aresame.html). If you want to check reference equality you have to use Assert.AreSame(). The output of Assert.AreEqual() depends fully on the object-type. – user1027167 Apr 28 '14 at 12:34
  • @user1027167 - clarified. In this case he wasn't trying to check reference equality but whether they contained the same content so I didn't think the answer needed that sort of precision. – tvanfosson Apr 28 '14 at 13:04
  • 2
    I recommend looking at the other CollectionAssert methods also...How long have I been using this unit testing framework and not known about CollectionAssert! I've been doing it manually for way too long and feel pretty dumb. –  Jul 27 '15 at 14:13
52

Because arrays don't override Equals.

You haven't said which test framework you're using, but basically it would be up to that framework to special-case arrays. You can always implement your own helper method to do that, of course. I've done that sometimes. For a quick and dirty hack, if you're using .NET 3.5 you can use the Enumerable.SequenceEqual extension method:

Assert.IsTrue(actual.SequenceEqual(expected));

A custom helper method could give you more details about how they differ, of course. You might find the methods in MoreLINQ.TestExtensions helpful, although they're fairly rough and ready too.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
5
//Initialize your arrays here
byte[] array1 = new byte[0];
byte[] array2 = new byte[0];

Assert.AreEqual(System.Convert.ToBase64String(array1),
                System.Convert.ToBase64String(array2));
Tommy Grovnes
  • 4,126
  • 2
  • 25
  • 40
José Brazeta
  • 77
  • 1
  • 3
  • 4
    Why convert the byte[] to a string to make the comparison. It is unnecessary and, imagine, the error could be in the conversion itself, not the byte[] – Luis Filipe Dec 23 '13 at 11:37
2

The method Assert.AreEqual under the hood will end up defaulting to Object.Equals() for non-null values. The default implementation of Object.Equals() is referential equality. The 2 arrays are identical value wise but difference reference wise and hence will not be considered equal.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
0

Created simple helper method:

private static void CompareArrays<T>(T[] expected, T[] actual)
{
    Assert.AreEqual(expected == null, actual == null, "Expected {0}null value and {1}null found.", expected == null ? "" : "not", actual == null ? "" : "not");
    if (expected == null || actual == null)
            return;

    Assert.AreEqual(expected.LongLength, actual.LongLength, "Expected Length is {0} actual: {1}", expected.LongLength, actual.LongLength);

    for (int i = 0; i < expected.Length; i++)
    {
        Assert.AreEqual(expected[i], actual[i], "Values on index {0} are not equal. Expected {1} actual: {2}", i, expected[i], actual[i]);
    }
}
Gh61
  • 9,222
  • 4
  • 28
  • 39
-1
byte[] a = new byte[] {x, y, z...};
byte[] b = new byte[] {x, y, z...};
assertArrayEquals(a , b );

will compare the stuff... It works for me..

Nikolay Kostov
  • 16,433
  • 23
  • 85
  • 123