为什么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理查森

Answers:


140

Assert.Equals使用Equals方法测试,默认情况下使用引用相等,并且由于它们是不同的对象,因此它们不相等。您需要比较数组中的每个字节,并验证它们是否相等。一种实现方法是将它们转换为实现ICollection的对象,并改用CollectionAssert.AreEqual()


3
ICollection当然,数组已经是。甚至是一个IList。重要的是,您的“集合相等性”必须考虑排序(即集合必须等于序列,而不仅仅是数学集合)。
杰普·斯蒂格·尼尔森

这个回答是错误的!“ Assert.AreEqual检查objectOne.Equals(objectTwo)将返回true。” (请参阅blog.robustsoftware.co.uk/2009/05/…)。如果要检查引用是否相等,则必须使用Assert.AreSame()。Assert.AreEqual()的输出完全取决于对象类型。
user1027167 2014年

@ user1027167-已澄清。在这种情况下,他不是要检查引用相等性,而是要检查它们是否包含相同的内容,因此我认为答案不需要那么精确。
tvanfosson

2
我建议也查看其他CollectionAssert方法...我已经使用这个单元测试框架多长时间了,对CollectionAssert还是一无所知!我已经手工做了太久了,感觉很傻。

44

因为数组不会覆盖Equals

您没有说要使用哪个测试框架,但是基本上,要由特殊框架的框架来决定。当然,您始终可以实现自己的帮助方法。有时候我已经做到了。对于快速又肮脏的黑客,如果您使用的是.NET 3.5,则可以使用Enumerable.SequenceEqual扩展方法:

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

当然,自定义帮助程序方法可以为您提供有关它们之间的区别的更多详细信息。您可能会发现这些方法MoreLINQ.TestExtensions很有用,尽管它们也相当粗糙且已经准备就绪。


我正在使用VSTS单元测试。是否有我可以使用的内置替代断言,或者进行for循环并比较字节,如果它们全部相等,则进行断言?
David Anderson

恐怕我还没有使用过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 []转换为字符串以进行比较。这是没有必要的,并且可以想象,错误可能出在转换本身,而不是字节[]
Luis Filipe

2

幕后的方法Assert.AreEqual将最终默认为非空值的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]);
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.