Почему Assert.AreEqual (T obj1, Tobj2) не работает с идентичными байтовыми массивами

86

У меня есть два идентичных байтовых массива в следующем сегменте кода:

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

Оба массива идентичны до самого байта. Почему в этом случае Assert.AreEqual завершится ошибкой?

Дэвид Андерсон
источник
1
Обратите внимание: если вы используете NUnit, сравнение значений массивов поддерживается начиная с версии 2.2, поэтому все Assert.AreEqualбудет работать нормально.
AJ Richardson

Ответы:

141

Assert.Equalsтесты с использованием Equalsметода, который по умолчанию использует ссылочное равенство и, поскольку это разные объекты, они не равны. Вы захотите сравнить каждый байт в массиве и убедиться, что они равны. Один из способов сделать это - преобразовать их во что-то, что реализует ICollection, и вместо этого использовать CollectionAssert.AreEqual () .

tvanfosson
источник
3
ICollectionКонечно, массив уже есть . Это даже файл IList. Важно, чтобы ваше «равенство коллекций» учитывало порядок (т.е. коллекции должны быть равны как последовательности, а не только как математические множества).
Jeppe Stig Nielsen
Это неправильный ответ! «Assert.AreEqual проверяет, что objectOne.Equals (objectTwo) вернет истину». (см. blog.robustsoftware.co.uk/2009/05/… ). Если вы хотите проверить ссылочное равенство, вы должны использовать Assert.AreSame (). Вывод Assert.AreEqual () полностью зависит от типа объекта.
user1027167
@ user1027167 - уточнил. В данном случае он пытался проверить не равенство ссылок, а то, содержат ли они одинаковый контент, поэтому я не думал, что ответ требует такой точности.
tvanfosson
2
Я также рекомендую взглянуть на другие методы CollectionAssert ... Как долго я использую эту среду модульного тестирования и ничего не знаю о CollectionAssert! Я слишком долго делал это вручную и чувствую себя довольно глупо.
44

Потому что массивы не отменяют Equals.

Вы не сказали, какую платформу тестирования вы используете, но в основном это будет зависеть от этой структуры для специальных массивов. Конечно, вы всегда можете реализовать свой собственный вспомогательный метод. Иногда я так поступал. Для быстрого и грязного взлома, если вы используете .NET 3.5, вы можете использовать Enumerable.SequenceEqualметод расширения:

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

Разумеется, специальный вспомогательный метод может дать вам более подробную информацию о том, чем они отличаются. Вы можете найти методы MoreLINQ.TestExtensionsполезными, хотя они тоже довольно грубые и готовые.

Джон Скит
источник
Я использую модульные тесты VSTS. Есть ли встроенное альтернативное утверждение, которое я могу использовать, или выполнить цикл for и сравнить байты, если они все равны, затем подтвердить?
Дэвид Андерсон,
Боюсь, что я не использовал модульные тесты VSTS, но рекомендация tvanfosson выглядит уместной.
Джон Скит,
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));
Хосе Бразета
источник
4
Зачем преобразовывать byte [] в строку для сравнения. В этом нет необходимости, и, представьте себе, ошибка могла быть в самом преобразовании, а не в байте []
Луис Филипе
2

Метод Assert.AreEqual под капотом в конечном итоге по умолчанию будет использовать Object.Equals () для ненулевых значений. Реализация Object.Equals () по умолчанию - ссылочное равенство. Два массива имеют одинаковое значение, но различаются по ссылкам и, следовательно, не будут считаться равными.

ДжаредПар
источник
0
byte[] a = new byte[] {x, y, z...};
byte[] b = new byte[] {x, y, z...};
assertArrayEquals(a , b );

буду сравнивать материал ... У меня работает ..

user2682078
источник
0

Создан простой вспомогательный метод:

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
источник