Pourquoi Assert.AreEqual (T obj1, Tobj2) échoue avec des tableaux d'octets identiques

86

J'ai deux tableaux d'octets identiques dans le segment de code suivant:

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

Les deux tableaux sont identiques jusqu'à l'octet même. Dans ce scénario, pourquoi Assert.AreEqual échouerait-il?

David Anderson
la source
1
En guise de note, si vous utilisez NUnit, les comparaisons de valeurs de tableaux sont prises en charge depuis la version 2.2, donc Assert.AreEqualfonctionnera correctement.
AJ Richardson

Réponses:

141

Assert.Equalstests utilisant la Equalsméthode, qui par défaut utilise l'égalité de référence et, comme ce sont des objets différents, ils ne sont pas égaux. Vous voudrez comparer chaque octet du tableau et vérifier qu'ils sont égaux. Une façon de le faire est de les convertir en quelque chose qui implémente ICollection et d'utiliser CollectionAssert.AreEqual () à la place.

Tvanfosson
la source
3
Un tableau est déjà un ICollection, bien sûr. C'est même un IList. Il est important que votre «égalité de collection» considère l'ordre (c'est-à-dire que les collections doivent être égales en tant que séquences, pas seulement en tant qu'ensembles mathématiques).
Jeppe Stig Nielsen
Cette réponse est fausse! "Assert.AreEqual vérifie que objectOne.Equals (objectTwo) retournera true." (voir blog.robustsoftware.co.uk/2009/05/… ). Si vous voulez vérifier l'égalité des références, vous devez utiliser Assert.AreSame (). La sortie de Assert.AreEqual () dépend entièrement du type d'objet.
user1027167
@ user1027167 - clarifié. Dans ce cas, il n'essayait pas de vérifier l'égalité des références, mais si elles contenaient le même contenu, je ne pensais donc pas que la réponse nécessitait ce genre de précision.
tvanfosson
2
Je recommande de regarder les autres méthodes de CollectionAssert également ... Depuis combien de temps j'utilise ce framework de test unitaire et je ne connais pas CollectionAssert! Je le fais manuellement depuis trop longtemps et je me sens assez stupide.
44

Parce que les tableaux ne remplacent pas Equals.

Vous n'avez pas dit quel framework de test vous utilisez, mais en gros, ce serait à ce framework de gérer des tableaux de cas spéciaux. Vous pouvez toujours implémenter votre propre méthode d'assistance pour ce faire, bien sûr. J'ai fait ça parfois. Pour un hack rapide et sale, si vous utilisez .NET 3.5, vous pouvez utiliser la Enumerable.SequenceEqualméthode d'extension:

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

Une méthode d'assistance personnalisée pourrait vous donner plus de détails sur leurs différences, bien sûr. Vous trouverez peut-être les méthodes MoreLINQ.TestExtensionsutiles, même si elles sont assez approximatives et prêtes aussi.

Jon Skeet
la source
J'utilise des tests unitaires VSTS. Y a-t-il une assertion alternative intégrée que je peux utiliser, ou faire une boucle for et comparer les octets, s'ils sont tous égaux, alors affirmer?
David Anderson
J'ai bien peur de ne pas avoir utilisé les tests unitaires VSTS - mais la recommandation de tvanfosson semble appropriée.
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
la source
4
Pourquoi convertir l'octet [] en chaîne pour effectuer la comparaison. Ce n'est pas nécessaire et, imaginez, l'erreur pourrait être dans la conversion elle-même, pas dans l'octet []
Luis Filipe
2

La méthode Assert.AreEqual sous le capot finira par utiliser par défaut Object.Equals () pour les valeurs non nulles. L'implémentation par défaut d'Object.Equals () est l'égalité référentielle. Les 2 tableaux sont identiques en termes de valeur mais diffèrent en termes de référence et ne seront donc pas considérés comme égaux.

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

va comparer les trucs ... ça marche pour moi ..

user2682078
la source
0

Création d'une méthode d'aide simple:

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
la source