【问题标题】:Why does Assert.AreEqual(T obj1, Tobj2) fail with identical byte arrays为什么 Assert.AreEqual(T obj1, Tobj2) 使用相同的字节数组失败
【发布时间】:2010-11-25 09:35:54
【问题描述】:

我在以下代码段中有两个相同的字节数组:

    /// <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 会失败?

【问题讨论】:

  • 请注意,如果您使用 NUnit,则从 2.2 版本开始支持数组的值比较,因此 Assert.AreEqual 可以正常工作。

标签: c# unit-testing assert


【解决方案1】:

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

【讨论】:

  • 当然,数组已经是ICollection。甚至是IList。重要的是您的“集合相等性”考虑排序(即集合必须与序列相等,而不仅仅是数学集合)。
  • 这个回答错了! “Assert.AreEqual 检查 objectOne.Equals(objectTwo) 是否会返回 true。” (见blog.robustsoftware.co.uk/2009/05/…)。如果要检查引用相等性,则必须使用 Assert.AreSame()。 Assert.AreEqual() 的输出完全取决于对象类型。
  • @user1027167 - 已澄清。在这种情况下,他不是要检查引用相等性,而是检查它们是否包含相同的内容,所以我认为答案不需要那种精确度。
  • 我建议也看看其他的 CollectionAssert 方法...我使用这个单元测试框架有多久了,还不知道 CollectionAssert!我手动操作太久了,感觉很笨。
【解决方案2】:

因为数组不会覆盖Equals。

您还没有说您正在使用哪个测试框架,但基本上它取决于该框架来处理特殊情况的数组。当然,您总是可以实现自己的辅助方法来做到这一点。我有时会这样做。如果您使用的是 .NET 3.5,则可以使用Enumerable.SequenceEqual 扩展方法进行快速而肮脏的破解:

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

当然,自定义辅助方法可以为您提供有关它们之间差异的更多详细信息。您可能会发现 MoreLINQ.TestExtensions 中的方法很有帮助,尽管它们也相当粗糙且准备就绪。

【讨论】:

  • 我正在使用 VSTS 单元测试。有没有我可以使用的内置替代断言,或者做一个 for 循环并比较字节,如果它们都相等,那么断言?
  • 恐怕我没有使用过 VSTS 单元测试 - 但 tvanfosson 的建议看起来很合适。
【解决方案3】:
//Initialize your arrays here
byte[] array1 = new byte[0];
byte[] array2 = new byte[0];

Assert.AreEqual(System.Convert.ToBase64String(array1),
                System.Convert.ToBase64String(array2));

【讨论】:

  • 为什么要将 byte[] 转换为字符串进行比较。这是不必要的,想象一下,错误可能出在转换本身,而不是 byte[]
【解决方案4】:

底层的 Assert.AreEqual 方法最终将默认为 Object.Equals() 用于非空值。 Object.Equals() 的默认实现是引用相等。这两个数组在值方面是相同的,但在参考方面是不同的,因此不会被认为是相等的。

【讨论】:

    【解决方案5】:

    创建了简单的辅助方法:

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

    【讨论】:

      【解决方案6】:
      byte[] a = new byte[] {x, y, z...};
      byte[] b = new byte[] {x, y, z...};
      assertArrayEquals(a , b );
      

      会比较这些东西...它对我有用..

      【讨论】:

      • 函数assertArrayEquals是从哪里来的?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      相关资源
      最近更新 更多