我试图为我的测试设置一些测试用例:
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(&#34; XS&#34;,&#34; XL&#34;,&#34; M&#34;)
消息:提供的参数数量错误
判断错误似乎解开数组并尝试将其应用于测试函数,但这当然会导致问题。我该如何解决这个问题?
答案 0 :(得分:3)
要使其正常工作,您需要将参数包装在这样的数组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));
}
答案 1 :(得分:2)
相关的实例构造函数具有以下重载:
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
的重载可以通过两种方式应用,可以是普通形式,您可以在代码中明确地提供对象数组,也可以扩展形式您只需用逗号指定一堆对象(零或多个),编译器就会隐式生成数组。请参阅C#规范中的§7.5.3.1适用的函数成员。
当你这样做时:
new TestCaseData(new string[] { "XS", "XL", "M" })
对于引用类型数组(string
是引用类型),C#(以及CLR)具有可疑的数组协方差变得很重要。因此,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#重载决策在这种情况下选择了什么,我们都很高兴。< / p>
实际上,在这种情况下,C#规则(第7.5.3.2节)更喜欢通常的形式而非扩展形式,因此使用//B
。这是一件好事,编译器不必创建隐式的长度为1的对象数组。