当TestCase中包含一个数组时,NUnit无法识别该TestCase

36
这是我在使用NUnit时遇到的一个非常简单但令人讨厌的问题:
我有一些测试用例像这样:
[Test]
[TestCase( 1, 2, "hello" )]
[TestCase( 3, 5, "goodbye" )]
public void MyClass_MyMethod( int a, int b, string c )
{
    Assert.IsTrue( a < b );
}

这很好运作,在ReSharper NUnit窗格中,我可以看到每个TestCase在结果中都有自己的响应。

我有第二个TestCase,它看起来像这样:

[Test]
[TestCase( 1, 2, new long[] { 100, 200 })]
[TestCase( 5, 3, new long[] { 300, 500 })]
public void MyClass_MyOtherMethod( long a, long b, long[] bunchOfNumbers )
{
   Assert.IsTrue( a < b );
}

运行时出现以下情况:

一个或多个子测试出现错误,异常没有堆栈跟踪

public void MyClass_MyOtherMethod(5,3,System.Int64[]) 失败

与其他测试不同的是,我的其他测试在测试列表中将每个TestCase绘制为单独的复选框,而此测试不会显示出来,直到我在调试器中运行它才能知道出了什么问题和在哪里。我有点担心这个测试在构建机器上的行为。有谁知道发生了什么以及为什么吗?


1
可能也是 ReSharper 测试运行器不支持它。 - Torbjörn Kalin
好的,会去检查NUnit控制台。 - glenatron
你使用的NUnit和Resharper版本是什么?我记得其中一个版本的一些问题在更晚的版本中得到了修复。 - Mikhail Brinchuk
顺便问一下,您有没有尝试使用 params 修饰符来传递此数组? - Mikhail Brinchuk
NUnit 2.6.2 对 ReSharper 7.1 - 可能需要向 Jetbrains 提出此问题。params 修饰符是用来做什么的? - glenatron
5个回答

37

参考JetBrains上的这个bug,似乎解决方案是在不同用例上使用TestName属性:

[Test]
[TestCase( 1, 2, new long[] { 100, 200 }, TestName="Test 1" )]
[TestCase( 5, 3, new long[] { 300, 500 }, TestName="Test 2" )]
public void MyClass_MyOtherMethod( long a, long b, long[] bunchOfNumbers )
{
   Assert.IsTrue( a < b );
}

如果我的测试失败,现在ReSharper中所有内容都可以正确显示了。


3
看起来在当前版本的 NUnit 和 ReSharper 中,不再需要这个解决方法。 - arni
5
如果您的第一个参数是数组,它仍然不会喜欢它。 - Jacob Brewer
但是如果您在参数列表中有多个数组,则它可以正常工作。 - vgaltes
5
这是因为 TestCase 的签名要求其第一个参数为 params object[] - 因此传递一个数组将导致 nUnit 寻找测试方法签名,其中参数的类型和长度与数组匹配。 - Oliver

17

对于包含字符串的数组,使用带有TestCase属性和paramsobject数组:

[Test]
[TestCase(new object[] {"foo", "bar", "baz"})]
[TestCase(new object[] {"300", "500", "700"})]    
public void MyClass_SomeOtherMethod(params string[] bunchOfStrings)
{
    // assert something...
}

6
对我来说,使用NUnit适配器的MSTest并没有完全成功。错误消息为“提供了太多参数,请最多提供1个参数。” 这必须是在测试运行器级别上,因为我甚至无法进入测试。 在测试方法签名中添加“params”关键字解决了这个问题。 - user1007074
感谢 @user1007074。已经使用您的修复更新了答案。 - Ray
对于Rider 2020.3.2,这是使用单个数组参数进行单元测试的方法。 - rgvlee
这对于 .Net 6.0 项目以及我正在使用的任何 NUnit 版本都不起作用。它会抛出一个错误:无法将类型为“System.Object[]”的对象转换为类型“System.String[]”。你必须将其声明为字符串,或者只需使用“new[]”来最小化它,而不是使用“new object[]”。 - computercarguy

4

另一种方法是使用一个字符串来表示数组:

[TestCase( 1, 2, "100, 200")]
[TestCase( 5, 3, "300, 500")]
public void MyClass_MyOtherMethod(long a, long b, string bunchOfNumbersString)
{
    var bunchOfNumbers= bunchOfNumbersString.Split(',')
                                            .Select(long.Parse)
                                            .ToArray();
   ...
}

采用这种方法的好处是在测试运行器中可以良好地呈现。
顺便说一下,使用 [TestCase] 时不需要 [Test],或者至少我没有看到它解决了什么问题。

2

我遇到了一个问题,就是参数的顺序很重要。使用的是 Rider 2020.1.4。

[TestCase(new string[] { "ABC", "DEF" }, false)]
public void SomeTestWithParams(string[] stringArr, bool someBool) {}

给了我一个错误,但是

[TestCase(false, new string[] { "ABC", "DEF" })]
public void SomeTestWithParams(bool someBool, string[] stringArr) {}

正常工作得很好


1
第二个可以工作是因为在TestCase函数中,您不能直接传递数组。您可以将第一个参数作为int / string / bool传递,然后允许第二个参数为数组,或者您可以在testCase函数中使用“new object []”,然后直接传递数组。 - Ankush

1
这在使用 NUnit 3.11.0 的 VS 2017 中有效。
[TestCase(new long[] {5, 6, 942135153})]
public void DummyTest(long[] values)
{
    Assert.That(values != null);
}

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