NUnit TestCaseData 的参数数量错误
本文关键字:错误 数数 参数 TestCaseData NUnit | 更新日期: 2023-09-27 18:02:29
我正在尝试为我的测试设置一些测试用例:
public IEnumerable<TestCaseData> size_tests()
{
yield return new TestCaseData(new string[] { "XS", "XL", "M" })
.Returns(new SortedVariantAttributeModel {
Values = new string[] { "XS", "M", "XL" },
PrimaryValue = "XS"
});
}
[Test, TestCaseSource("size_tests")]
public SortedVariantAttributeModel Should_map_SortedVariantAttributes(string[] sizes)
{
// ...
}
当我尝试运行此测试时,我得到:
测试失败 - Should_map_SortedVariantAttributes("XS","XL","M"(
消息:提供的参数数量错误
从错误来看,它似乎解开了数组并尝试将其应用于测试函数,但这当然会导致问题。我该如何解决这个问题?
要使其正常工作,您需要将参数包装在这样的数组中,new[] { new string[] { "XS", "XL", "M" } }
.这会导致 NUnit 将字符串数组视为方法的第一个参数,而不是一系列字符串参数。
我相信您正在使用 NUnit 2.x,因为您的数据源不是静态的。我简化了您的代码并测试了 NUnit 2.6.4 和 3.4.1 中的解决方法。
public static IEnumerable<TestCaseData> Data()
{
yield return new TestCaseData(new[] { new string[] { "XS", "XL", "M" } });
yield return new TestCaseData(new[] { new string[] { "S", "M", "XXL", "L" } });
}
[TestCaseSource(nameof(Data))]
public void TestStringArrayArguments(string[] sizes)
{
Assert.That(sizes.Length, Is.GreaterThan(1));
}
相关的实例构造函数具有以下重载:
public TestCaseData(params object[] args) { /* ... */ } //A
public TestCaseData(object arg) { /* ... */ } //B
public TestCaseData(object arg1, object arg2) { /* ... */ } //C
public TestCaseData(object arg1, object arg2, object arg3) { /* ... */ } //D
params
重载可以通过两种方式应用,一种是普通形式,即在代码中显式提供对象数组,另一种是扩展形式,只需用逗号指定一堆对象(零个或多个(,编译器就会隐式生成数组。请参阅 §7.5.3.1 C# 规范中的适用函数成员。
当您执行以下操作时:
new TestCaseData(new string[] { "XS", "XL", "M" })
重要的是,C#(以及CLR(对于引用类型的数组(string
是引用类型(的数组协方差可疑。所以你的string[]
"是"也是一个object[]
(对string
是一个object
的事实使用协方差(。
因此,过载//A
以正常形式应用。当适用正常形式时,不应考虑扩展形式的//A
。
使用中的过载//B
也适用,因为string[]
是一个System.Array
,它是一个object
。
但是,//A
被认为更具体(所有object[]
都object
,但现在反之亦然(,并且优于//B
。因此,//A
以正常形式使用,这不是您想要的。您的Should_map_SortedVariantAttributes
需要一个参数(称为sizes
(,而不是三个。因此问题来了。
一个好的解决方案现在很容易:
new TestCaseData((object)(new string[] { "XS", "XL", "M" })) /* fixes your issue! */
现在我们有一个类型 object
的表达式。重载//A
不再以正常形式适用。因此,这次检查//A
是否适用于其扩展形式,确实如此。
//B
也适用于这里。
无论是扩展形式的//A
还是//B
都会使代码正常工作,因此在这种情况下,无论 C# 重载分辨率选择什么,我们都很高兴。
实际上,在这种情况下,C# 规则 (§7.5.3.2( 更喜欢常用形式而不是扩展形式,因此使用//B
。这是一件好事,编译器不必创建隐式 length-1 对象数组。