You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#单元测试中双字节数组DataRow仅生效最后一行的问题排查

问题描述

编写包含多个[DataRow]的[DataTestMethod]时,每个DataRow传入两个byte数组,但测试仅执行最后一行DataRow的用例。此前仅含整数、或单个byte数组搭配bool值的DataRow测试均可正常运行,仅双byte数组的多DataRow测试异常。

正常工作的测试代码

[DataTestMethod]
[DataRow(1, 1, 2)]
[DataRow(2, 2, 4)]
[DataRow(3, 3, 6)]
public void AddTests(int x, int y, int expected)
{
    Assert.AreEqual(expected, x + y);
}

[DataRow(new byte[] { 0x00 }, false, false, false)]
[DataRow(new byte[] { 0x00 }, true, true, false)]
[DataRow(new byte[] { 0x00 }, false, true, false)]
[DataRow(new byte[] { 0x00 }, true, false, false)]
[DataTestMethod()]
public void ByteArrayIntegerTest(byte[] key,bool ctorsign, bool tasign,bool expectfail)
{
    var bi = new ByteArrayInteger(key, ctorsign);
    var result = bi.ToByteArray(tasign);
    if (expectfail)
    {
        CollectionAssert.AreNotEqual(key, result);
    }
    else
    {
        CollectionAssert.AreEqual(key, result);
    }
}

无法正常工作的测试代码

[DataTestMethod]
[DataRow(new byte[] { 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE })]
[DataRow(new byte[] { 0x00, 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE })]
[DataRow(new byte[] { 0x00, 0x00, 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE })]

public void MinimizeSerialnumberTest(byte[] serialnumber, byte[] expected)
{
    CollectionAssert.AreEqual(expected, Util.MinimizeSerialnumber(serialnumber));
}

测试无报错,但仅执行最后一行DataRow的测试用例。疑问:Microsoft.VisualStudio.TestTools.UnitTesting不支持多byte数组的DataRow吗?是否因为DataRowAttribute的构造函数参数为Object, Object[]导致该问题?如何解决?

问题原因与解决方案

原因

问题确实和DataRowAttribute的构造函数参数机制有关。DataRowAttribute的构造参数要求是编译时常量,而byte数组属于引用类型,在多个DataRow中初始化的数组会被框架错误地共享引用——后续DataRow的数组会覆盖前面的实例,最终所有测试用例都指向最后一个DataRow的数组对象。

解决方案

推荐使用DynamicDataAttribute替代DataRowAttribute,它支持动态生成测试数据,能正确处理引用类型的参数传递,避免数组引用被复用的问题。

示例代码改造如下:

[DataTestMethod]
[DynamicData(nameof(GetMinimizeSerialnumberTestData), DynamicDataSourceType.Method)]
public void MinimizeSerialnumberTest(byte[] serialnumber, byte[] expected)
{
    CollectionAssert.AreEqual(expected, Util.MinimizeSerialnumber(serialnumber));
}

// 静态方法提供测试数据
public static IEnumerable<object[]> GetMinimizeSerialnumberTestData()
{
    yield return new object[] { new byte[] { 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE } };
    yield return new object[] { new byte[] { 0x00, 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE } };
    yield return new object[] { new byte[] { 0x00, 0x00, 0xCA, 0xFE }, new byte[] { 0xCA, 0xFE } };
}

其他可选方案

如果坚持使用DataRowAttribute,可以通过将byte数组强制转换为object类型,避免引用复用问题(但这种方式可靠性较低,不推荐):

[DataTestMethod]
[DataRow((object)new byte[] { 0xCA, 0xFE }, (object)new byte[] { 0xCA, 0xFE })]
[DataRow((object)new byte[] { 0x00, 0xCA, 0xFE }, (object)new byte[] { 0xCA, 0xFE })]
[DataRow((object)new byte[] { 0x00, 0x00, 0xCA, 0xFE }, (object)new byte[] { 0xCA, 0xFE })]

内容的提问来源于stack exchange,提问作者Sven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 15:03:34