Чому 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,

Відповіді:


140

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


3
Масив - це вже ICollection, звичайно. Це навіть IList. Важливо, щоб ваша "рівність колекції" враховувала впорядкування (тобто колекції повинні бути рівними як послідовності, а не лише як математичні множини).
Jeppe Stig Nielsen

Цей відповідь помилковий! "Assert.AreEqual перевіряє, що objectOne.Equals (objectTwo) поверне true." (див. 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
Навіщо конвертувати байт [] у рядок для порівняння. Це непотрібно, і, уявіть, помилка могла бути в самому перетворенні, а не в байті []
Луїс Філіпе

2

Метод Assert.AreEqual під капотом призведе до значення Object.Equals () для ненульових значень. Реалізацією Object.Equals () за замовчуванням є посилальна рівність. Ці два масиви є однаковими за значенням, але різницеві посилання і тому не вважатимуться рівними.



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]);
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.