Warum schlägt Assert.AreEqual (T obj1, Tobj2) mit identischen Byte-Arrays fehl?

86

Ich habe zwei identische Byte-Arrays im folgenden Codesegment:

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

Beide Arrays sind bis auf das Byte identisch. Warum sollte Assert.AreEqual in diesem Szenario fehlschlagen?

David Anderson
quelle
1
Wenn Sie NUnit verwenden, werden Wertvergleiche von Arrays seit Version 2.2 unterstützt, sodass dies Assert.AreEqualproblemlos funktioniert.
AJ Richardson

Antworten:

139

Assert.EqualsTests mit der EqualsMethode, bei der standardmäßig die Referenzgleichheit verwendet wird. Da es sich um unterschiedliche Objekte handelt, sind sie nicht gleich. Sie möchten jedes Byte im Array vergleichen und überprüfen, ob es gleich ist. Eine Möglichkeit, dies zu tun, besteht darin, sie in etwas zu konvertieren, das ICollection implementiert, und stattdessen CollectionAssert.AreEqual () zu verwenden.

Tvanfosson
quelle
3
Ein Array ist ICollectionnatürlich schon ein . Es ist sogar ein IList. Es ist wichtig, dass Ihre "Sammlungsgleichheit" die Reihenfolge berücksichtigt (dh Sammlungen müssen als Sequenzen gleich sein, nicht nur als mathematische Mengen).
Jeppe Stig Nielsen
Diese Antwort ist falsch! "Assert.AreEqual überprüft, ob objectOne.Equals (objectTwo) true zurückgibt." (siehe blog.robustsoftware.co.uk/2009/05/… ). Wenn Sie die Referenzgleichheit überprüfen möchten, müssen Sie Assert.AreSame () verwenden. Die Ausgabe von Assert.AreEqual () hängt vollständig vom Objekttyp ab.
user1027167
@ user1027167 - geklärt. In diesem Fall versuchte er nicht, die Referenzgleichheit zu überprüfen, sondern ob sie denselben Inhalt enthielten, sodass ich nicht glaubte, dass die Antwort diese Präzision erforderte.
Tvanfosson
2
Ich empfehle, auch die anderen CollectionAssert-Methoden zu betrachten ... Wie lange verwende ich dieses Unit-Testing-Framework und bin nicht über CollectionAssert bekannt! Ich mache es viel zu lange manuell und fühle mich ziemlich dumm.
44

Weil Arrays nicht überschreiben Equals.

Sie haben nicht gesagt, welches Testframework Sie verwenden, aber im Grunde liegt es an diesem Framework, Arrays für Sonderfälle zu erstellen. Natürlich können Sie dazu jederzeit Ihre eigene Hilfsmethode implementieren. Ich habe das manchmal gemacht. Wenn Sie .NET 3.5 verwenden, können Sie für einen schnellen und schmutzigen Hack die Enumerable.SequenceEqualErweiterungsmethode verwenden:

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

Eine benutzerdefinierte Hilfsmethode kann Ihnen natürlich mehr Details darüber geben, wie sie sich unterscheiden. Sie finden die Methoden möglicherweise MoreLINQ.TestExtensionshilfreich, obwohl sie auch ziemlich grob und bereit sind.

Jon Skeet
quelle
Ich verwende VSTS-Unit-Tests. Gibt es eine eingebaute alternative Zusicherung, die ich verwenden oder eine for-Schleife ausführen und die Bytes vergleichen kann, wenn sie alle gleich sind, dann behaupten?
David Anderson
Ich fürchte, ich habe keine VSTS-Komponententests verwendet - aber die Empfehlung von tvanfosson sieht angemessen aus.
Jon Skeet
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));
José Brazeta
quelle
4
Warum das Byte [] in einen String konvertieren, um den Vergleich durchzuführen? Es ist unnötig und stellen Sie sich vor, der Fehler könnte in der Konvertierung selbst liegen, nicht im Byte []
Luis Filipe
2

Die Methode Assert.AreEqual unter der Haube verwendet standardmäßig Object.Equals () für Werte ungleich Null. Die Standardimplementierung von Object.Equals () ist die referenzielle Gleichheit. Die 2 Arrays sind hinsichtlich des Werts identisch, aber hinsichtlich der Differenz referenziert und werden daher nicht als gleich angesehen.

JaredPar
quelle
0
byte[] a = new byte[] {x, y, z...};
byte[] b = new byte[] {x, y, z...};
assertArrayEquals(a , b );

werde das Zeug vergleichen ... Es funktioniert für mich ..

user2682078
quelle
0

Einfache Hilfsmethode erstellt:

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
quelle