如何使用xUnit测试byte[]数组?

4

我对C#单元测试和xUnit很陌生。那么,测试byte[]数组的正确方法是什么?

我试图测试原始数据包到对象再到原始数据包的过程。

[Fact]
public void DiscoverTest()
{
    // DHCP Discover packet (#1) from 
    // https://wiki.wireshark.org/DHCP
    // https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=view&target=dhcp.pcap
    // Ethernet and UDP metadata stripped
    byte[] b = new byte[]
    {
       0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x3d, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x0b, 0x82, 0x01, 0xfc, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
       0x53, 0x63, 0x35, 0x01, 0x01, 0x3d, 0x07, 0x01, 0x00, 0x0b, 0x82, 0x01, 0xfc, 0x42,
       0x32, 0x04, 0x00, 0x00, 0x00, 0x00, 0x37, 0x04, 0x01, 0x03, 0x06, 0x2a, 0xff, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    // raw byte[] to object's properties etc
    DHCPPacket p = new DHCPPacket(b);

    // p.GetRawBytes() object properties etc to raw byte[]
    Assert.Equal<byte[]>(b, p.GetRawBytes());
}

这将会得到:
Assert.Equal() Failure
Expected: Byte[] [1, 1, 6, 0, 0, ...]
Actual:   Byte[] [1, 1, 6, 0, 0, ...]

所以我无法看到数据错在哪个偏移量。

正确的方式是什么?

我正在使用xUnit 2.2.0。


断言两个对象相等时使用它们的默认相等比较器。由于 byte[] 没有重写 .Equals,因此您正在比较字节数组的引用而不是它们的内容。如果要比较内容,则必须自己循环遍历它们或使用 BitConverter 或类似工具将它们转换为字符串。 - kanders84152
2个回答

3

正如评论中指出的那样,必须迭代数组:

byte[] pb = new DHCPPacket(b).GetRawBytes();

for (int i = 0; i < b.Length; i++)
{
    byte expected = b[i];
    byte actual = pb[i];

    Assert.True(expected == actual, 
        String.Format("Expected: '{0}', Actual: '{1}' at offset {2}.", (byte)expected, (byte)actual, i)
    );
}

1
XUnit中的单元测试在第一个断言失败。如果您首先进行长度断言,就能知道哪个长度是错误的。
Assert.Equal(b.Length, p.GetRawBytes().Length);
Assert.Equal<byte[]>(b, p.GetRawBytes());

Assert.Equal 还可以接受一个可选的第三个参数,用于在测试失败时打印。因此你可以这样写:

Assert.Equal(b.Length, p.GetRawBytes().Length, $"Byte array lengths different. Expected: {b.length}, Actual: {p.GetRawBytes().Length}");

在这种情况下,长度是正确的,但是偏移量X之后的原始byte[]数据不正确。因此,我想看到数组的差异或第一个不正确字节的偏移量,以便我可以在GetRawBytes方法中找到罪魁祸首。在这个例子中,我删除了额外的长度检查断言。 - raspi
@raspi 至少你可以提供自己的消息,这样你就可以构建一条消息,以展示在哪个偏移量上有什么不同。 - Evk
我认为要做到这一点,您需要迭代每个字节数组并查看哪一个不同。 - Dan Schnau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接