¿Por qué Assert.AreEqual (T obj1, Tobj2) falla con matrices de bytes idénticas?

86

Tengo dos matrices de bytes idénticas en el siguiente segmento de código:

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

Ambas matrices son idénticas hasta el mismo byte. En este escenario, ¿por qué fallaría Assert.AreEqual?

David Anderson
fuente
1
Como nota, si usa NUnit, las comparaciones de valores de matrices son compatibles desde la versión 2.2, por Assert.AreEquallo que funcionará bien.
AJ Richardson

Respuestas:

141

Assert.Equalspruebas usando el Equalsmétodo, que por defecto usa igualdad de referencia y, al ser objetos diferentes, no son iguales. Querrá comparar cada byte en la matriz y verificar que sean iguales. Una forma de hacer esto es convertirlos en algo que implemente ICollection y usar CollectionAssert.AreEqual () en su lugar.

tvanfosson
fuente
3
Una matriz ya es una ICollection, por supuesto. Incluso es un IList. Es importante que su "igualdad de colección" considere el orden (es decir, las colecciones deben ser iguales como secuencias, no solo como conjuntos matemáticos).
Jeppe Stig Nielsen
¡Esta respuesta es incorrecta! "Assert.AreEqual comprueba que objectOne.Equals (objectTwo) devolverá verdadero". (ver blog.robustsoftware.co.uk/2009/05/… ). Si desea verificar la igualdad de referencia, debe usar Assert.AreSame (). La salida de Assert.AreEqual () depende completamente del tipo de objeto.
user1027167
@ user1027167 - aclarado. En este caso, no estaba tratando de verificar la igualdad de referencias, sino si tenían el mismo contenido, así que no pensé que la respuesta necesitara ese tipo de precisión.
tvanfosson
2
Recomiendo mirar también los otros métodos CollectionAssert ... ¿Cuánto tiempo he estado usando este marco de pruebas unitarias y no conozco CollectionAssert? Lo he estado haciendo manualmente durante demasiado tiempo y me siento bastante tonto.
44

Porque las matrices no anulan Equals.

No ha dicho qué marco de prueba está usando, pero básicamente dependerá de ese marco para matrices de casos especiales. Siempre puede implementar su propio método de ayuda para hacer eso, por supuesto. A veces he hecho eso. Para un truco rápido y sucio, si está usando .NET 3.5, puede usar el Enumerable.SequenceEqualmétodo de extensión:

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

Por supuesto, un método de ayuda personalizado podría brindarle más detalles sobre cómo se diferencian. Es posible que encuentre los métodos MoreLINQ.TestExtensionsútiles, aunque también son bastante toscos y están listos.

Jon Skeet
fuente
Estoy usando pruebas unitarias VSTS. ¿Hay una aserción alternativa incorporada que pueda usar, o hacer un bucle for y comparar los bytes, si todos son iguales, entonces afirmar?
David Anderson
Me temo que no he utilizado las pruebas unitarias VSTS, pero la recomendación de tvanfosson parece apropiada.
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
fuente
4
¿Por qué convertir el byte [] en una cadena para hacer la comparación? Es innecesario e, imagina, el error podría estar en la conversión en sí, no en el byte []
Luis Filipe
2

El método Assert.AreEqual bajo el capó terminará por defecto en Object.Equals () para valores no nulos. La implementación predeterminada de Object.Equals () es la igualdad referencial. Las 2 matrices son idénticas en cuanto a valor, pero en referencia a diferencias y, por lo tanto, no se considerarán iguales.

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

compararé las cosas ... Funciona para mí ..

user2682078
fuente
0

Método de ayuda simple creado:

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
fuente