Por que Assert.AreEqual (T obj1, Tobj2) falha com matrizes de bytes idênticas

86

Tenho duas matrizes de bytes idênticas no seguinte 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 as matrizes são idênticas até o byte. Nesse cenário, por que Assert.AreEqual falharia?

David Anderson
fonte
1
Como uma observação, se você usar o NUnit, comparações de valor de matrizes são suportadas desde a versão 2.2, portanto Assert.AreEqual, funcionarão bem.
AJ Richardson

Respostas:

139

Assert.Equalstesta usando o Equalsmétodo, que por padrão usa igualdade de referência e, por serem objetos diferentes, não são iguais. Você vai querer comparar cada byte na matriz e verificar se eles são iguais. Uma maneira de fazer isso é convertê-los em algo que implemente ICollection e usar CollectionAssert.AreEqual () .

Tvanfosson
fonte
3
Um array já é um ICollection, é claro. É até um IList. É importante que sua "igualdade de coleção" considere a ordenação (isto é, as coleções devem ser iguais como sequências, não apenas como conjuntos matemáticos).
Jeppe Stig Nielsen
Esta resposta está errada! "Assert.AreEqual verifica se objectOne.Equals (objectTwo) retornará verdadeiro." (consulte blog.robustsoftware.co.uk/2009/05/… ). Se você quiser verificar a igualdade de referência, você deve usar Assert.AreSame (). A saída de Assert.AreEqual () depende totalmente do tipo de objeto.
user1027167
@ user1027167 - esclarecido. Nesse caso, ele não estava tentando verificar a igualdade de referência, mas se elas continham o mesmo conteúdo, então não achei que a resposta precisasse desse tipo de precisão.
tvanfosson
2
Eu recomendo olhar para os outros métodos CollectionAssert também ... Há quanto tempo eu uso esta estrutura de teste de unidade e não conheço CollectionAssert! Tenho feito isso manualmente há muito tempo e me sinto muito idiota.
44

Porque os arrays não substituem Equals.

Você não disse qual framework de teste está usando, mas basicamente caberia a esse framework os arrays de casos especiais. Você sempre pode implementar seu próprio método auxiliar para fazer isso, é claro. Eu tenho feito isso algumas vezes. Para um hack rápido e sujo, se você estiver usando .NET 3.5, poderá usar o Enumerable.SequenceEqualmétodo de extensão:

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

Um método auxiliar personalizado pode fornecer mais detalhes sobre como eles diferem, é claro. Você pode achar os métodos MoreLINQ.TestExtensionsúteis, embora eles também sejam bastante rudimentares e prontos.

Jon Skeet
fonte
Estou usando testes de unidade VSTS. Existe uma asserção alternativa interna que eu possa usar ou fazer um loop for e comparar os bytes, se todos forem iguais, então afirmar?
David Anderson,
Infelizmente, não usei testes de unidade VSTS - mas a recomendação de tvanfosson parece apropriada.
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
fonte
4
Por que converter o byte [] em uma string para fazer a comparação. É desnecessário e, imagina, o erro pode estar na conversão em si, não no byte []
Luis Filipe
2

O método Assert.AreEqual subjacente acabará assumindo o padrão Object.Equals () para valores não nulos. A implementação padrão de Object.Equals () é a igualdade referencial. As 2 matrizes são idênticas em termos de valor, mas diferem em termos de referência e, portanto, não serão consideradas iguais.

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

vai comparar as coisas ... Funciona para mim ..

user2682078
fonte
0

Método auxiliar simples criado:

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
fonte