Dlaczego Assert.AreEqual (T obj1, Tobj2) kończy się niepowodzeniem z identycznymi tablicami bajtów

86

Mam dwie identyczne tablice bajtów w następującym segmencie kodu:

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

Obie tablice są identyczne co do samego bajtu. W tym scenariuszu, dlaczego Assert.AreEqual zawiedzie?

David Anderson
źródło
1
Uwaga: jeśli używasz NUnit, porównania wartości tablic są obsługiwane od wersji 2.2, więc Assert.AreEqualbędzie działać dobrze.
AJ Richardson

Odpowiedzi:

141

Assert.Equalstesty przy użyciu Equalsmetody, która domyślnie używa równości odwołań, a ponieważ są to różne obiekty, nie są równe. Będziesz chciał porównać każdy bajt w tablicy i sprawdzić, czy są równe. Jednym ze sposobów jest przekonwertowanie ich na coś, co implementuje ICollection i zamiast tego użycie CollectionAssert.AreEqual () .

tvanfosson
źródło
3
ICollectionOczywiście tablica już jest . To nawet IList. Ważne jest, aby Twoja „równość kolekcji” uwzględniała porządkowanie (tj. Zbiory muszą być równe jako sekwencje, a nie tylko jako zbiory matematyczne).
Jeppe Stig Nielsen
Ta odpowiedź jest nieprawidłowa! „Assert.AreEqual sprawdza, czy objectOne.Equals (objectTwo) zwróci wartość true”. (patrz blog.robustsoftware.co.uk/2009/05/ ... ). Jeśli chcesz sprawdzić równość odwołań, musisz użyć Assert.AreSame (). Wynik działania Assert.AreEqual () zależy w pełni od typu obiektu.
user1027167
@ user1027167 - wyjaśniono. W tym przypadku nie próbował sprawdzić równości odwołań, ale czy zawierają one tę samą treść, więc nie sądziłem, że odpowiedź wymaga takiej precyzji.
tvanfosson
2
Polecam również przyjrzeć się innym metodom CollectionAssert ... Jak długo używam tego frameworka do testów jednostkowych i nie wiem o CollectionAssert! Robiłem to ręcznie zbyt długo i czuję się dość głupio.
44

Ponieważ tablice nie zastępują Equals.

Nie powiedziałeś, którego frameworka testowego używasz, ale zasadniczo zależałoby to od tego frameworka do tablic specjalnych. Oczywiście zawsze możesz zaimplementować własną metodę pomocniczą, aby to zrobić. Czasami to robiłem. Jeśli używasz .NET 3.5, możesz skorzystać z Enumerable.SequenceEqualmetody rozszerzenia:

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

Oczywiście niestandardowa metoda pomocnicza może dostarczyć więcej informacji na temat różnic między nimi. Metody mogą okazać się MoreLINQ.TestExtensionspomocne, chociaż są one również dość szorstkie i gotowe.

Jon Skeet
źródło
Używam testów jednostkowych VSTS. Czy istnieje wbudowane alternatywne potwierdzenie, którego mogę użyć, lub wykonać pętlę for i porównać bajty, jeśli wszystkie są równe, a następnie potwierdzić?
David Anderson,
Obawiam się, że nie korzystałem z testów jednostkowych VSTS - ale zalecenie tvanfosson wygląda na odpowiednie.
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
źródło
4
Po co konwertować bajt [] na łańcuch, aby dokonać porównania. Jest to niepotrzebne i wyobraź sobie, że błąd może tkwić w samej konwersji, a nie w bajcie []
Luis Filipe
2

Metoda Assert.AreEqual pod maską zakończy się jako domyślna dla Object.Equals () dla wartości innych niż null. Domyślną implementacją Object.Equals () jest równość referencyjna. Te 2 tablice mają identyczne wartości, ale pod względem odniesienia do różnic, a zatem nie będą uważane za równe.

JaredPar
źródło
0
byte[] a = new byte[] {x, y, z...};
byte[] b = new byte[] {x, y, z...};
assertArrayEquals(a , b );

porówna rzeczy ... To działa dla mnie ...

user2682078
źródło
0

Utworzono prostą metodę pomocniczą:

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
źródło