35

This is quite simple but annoying behaviour I am running into with NUnit:

I have some tests like this:

[Test]
[TestCase( 1, 2, "hello" )]
[TestCase( 3, 5, "goodbye" )]
public void MyClass_MyMethod( int a, int b, string c )
{
    Assert.IsTrue( a < b );
}

This works fine and in the ReSharper NUnit pane I can see each TestCase getting its own response in the result.

I have a second TestCase that looks like this:

[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 );
}

When I run it I see this:

One or more child tests had errors Exception doesn't have a stacktrace

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

The difference being that with my other tests it draws out each TestCase as a separate checkbox on the test list, whereas this one does not get shown and I have no detail until I run it in a debugger as to what went wrong and where. I am a little concerned about how this test will behave on the build machine. Does anyone have any idea what is going on and why?

glenatron
  • 11,018
  • 13
  • 64
  • 112

5 Answers5

36

Following on from this bug at JetBrains it looks as though the solution here is to use the TestName attribute on your different cases:

[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 );
}

Everything now shows correctly in ReSharper if one of my tests fails.

glenatron
  • 11,018
  • 13
  • 64
  • 112
  • 3
    It looks like with current versions of NUnit and ReSharper this workaround is no longer required. – arni Oct 30 '14 at 17:08
  • 4
    It still doesn't like it if your first parameter is the array. – Jacob Brewer Mar 03 '15 at 15:29
  • But it works if you have more than one array in the parameter list. – vgaltes Jan 05 '16 at 20:56
  • 4
    @JacobBrewer: That's because the signature of `TestCase` expect `params object[]` as its first parameter - so passing in an array will lead to nUnit looking for a test method signature where the parameters match the type and length of the array. – Oliver Mar 30 '17 at 16:13
16

For an array that contains strings, use an object array with the TestCase attributes along with params:

[Test]
[TestCase(new object[] {"foo", "bar", "baz"})]
[TestCase(new object[] {"300", "500", "700"})]    
public void MyClass_SomeOtherMethod(params string[] bunchOfStrings)
{
    // assert something...
}
Ray
  • 187,153
  • 97
  • 222
  • 204
  • 6
    This didn't quite work for me, using MSTest with NUnit adapter. Error message was `Too many arguments provided, provide at most 1 arguments.` and this must have been at test runner level as I couldn't even step into the test. Adding `params` keyword in the test method signature did the trick. – user1007074 Nov 22 '18 at 17:48
  • Thanks @user1007074. Updated the answer with your fix. – Ray Sep 27 '19 at 17:34
  • For Rider 2020.3.2, this is the way for a unit test with a single array parameter. – rgvlee Feb 11 '21 at 09:06
  • This doesn't work for .Net 6.0 projects, and/or whatever version of NUnit I'm using. It throws an error: Object of type 'System.Object[]' cannot be converted to type 'System.String[]'. Instead of "new object[]", you have to declare it as a string, or just minimize it with "new[]". – computercarguy Mar 07 '23 at 22:53
4

An alternative is to use a string for the array:

[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();
   ...
}

The upside with this approach is that it will render nicly in the testrunner.

Side note: The [Test] is not needed when using [TestCase] or at least I don't see that it solves a problem.

Johan Larsson
  • 17,112
  • 9
  • 74
  • 88
2

I came across an issue with this where the order of the arguments mattered. Using Rider 2020.1.4

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

Gave me an error, but

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

worked just fine

ste-fu
  • 6,879
  • 3
  • 27
  • 46
  • 1
    second one works because in the TestCase function, you can not directly pass array. Either you pass the first arguemnt as int/string/bool and second argument is array is allowed Or you use the 'new object [] inside the testCase function then you are allowed to pass the array directly' – Ankush Feb 22 '22 at 08:57
1

This works in VS 2017 with NUnit 3.11.0

[TestCase(new long[] {5, 6, 942135153})]
public void DummyTest(long[] values)
{
    Assert.That(values != null);
}
Matt
  • 11
  • 3