Assert.AreEqual(T obj1、Tobj2)が同一のバイト配列で失敗するのはなぜですか


86

次のコードセグメントに2つの同一のバイト配列があります。

    /// <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リチャードソン

回答:


141

Assert.EqualsEqualsデフォルトで参照の同等性を使用するメソッドを使用してテストします。これらは異なるオブジェクトであるため、等しくありません。配列の各バイトを比較して、それらが等しいことを確認する必要があります。これを行う1つの方法は、それらをICollectionを実装するものに変換し、代わりにCollectionAssert.AreEqual()を使用することです。


3
ICollectionもちろん、配列はすでにです。それもIListです。「コレクションの同等性」が順序付けを考慮することが重要です(つまり、コレクションは数学的なセットとしてだけでなく、シーケンスとして等しくなければなりません)。
Jeppe Stig Nielsen 2012

この答えは間違っています!「Assert.AreEqualは、objectOne.Equals(objectTwo)がtrueを返すことを確認します。」(blog.robustsoftware.co.uk/2009/05/…を参照)。参照の同等性を確認する場合は、Assert.AreSame()を使用する必要があります。Assert.AreEqual()の出力は、オブジェクトタイプに完全に依存します。
user1027167 2014

@ user1027167-明確化。この場合、彼は参照の同等性をチェックしようとしていませんでしたが、それらが同じコンテンツを含んでいるかどうかをチェックしようとしていたので、答えにはそのような精度が必要だとは思いませんでした。
tvanfosson 2014

2
他のCollectionAssertメソッドも確認することをお勧めします...このユニットテストフレームワークをどのくらい使用していて、CollectionAssertについて知られていないのですか?私はそれをあまりにも長い間手動でやっていて、かなり馬鹿げていると感じています。

44

配列はオーバーライドしないためEqualsです。

使用しているテストフレームワークについてはまだ述べていませんが、基本的には、特殊なケースの配列についてはそのフレームワーク次第です。もちろん、それを行うためにいつでも独自のヘルパーメソッドを実装できます。私は時々それをしました。迅速で汚いハックのために、.NET 3.5を使用している場合は、Enumerable.SequenceEqual拡張メソッドを使用できます。

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

もちろん、カスタムヘルパーメソッドを使用すると、それらの違いについて詳細を知ることができます。これらの方法MoreLINQ.TestExtensionsはかなりラフで準備ができていますが、役立つかもしれません。


VSTSユニットテストを使用しています。使用できる組み込みの代替アサーションはありますか、またはforループを実行してバイトを比較し、すべてが等しい場合はアサートしますか?
デビッドアンダーソン

VSTSユニットテストを使用したことがないのではないかと思いますが、tvanfossonの推奨事項は適切に見えます。
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));

4
比較を行うためにbyte []を文字列に変換する理由。それは不要であり、想像してみてください。エラーはバイトではなく、変換自体にある可能性があります[]
ルイスフィリペ

2

内部のAssert.AreEqualメソッドは、null以外の値に対してデフォルトでObject.Equals()になります。Object.Equals()のデフォルトの実装は、参照の同等性です。2つの配列は、値に関しては同じですが、参照に関しては異なるため、等しいとは見なされません。


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

ものを比較します...それは私のために働きます..


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]);
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.