views:

1530

answers:

2

Hi, I have methods with more than one parameter that are guarded against bad input by throwing ArgumentNullExceptions and ArgumentExceptions whenever any parameter is null.

So there are two obvious ways to test this:

  • One test per Parameter using the [ExpectedException] attribute
  • One test for all parameters using multiple try{} catch blocks

The try catch thing would look like that:

try 
{
    controller.Foo(null, new SecondParameter());
    Assert.Fail("ArgumentNullException wasn't thrown");
} catch (ArgumentNullException)
{}

With one little problem. If the test passes, Assert.Fail never gets called and will therefore be highlighted as not covered test code (by NCover).

I know this isn't actually a problem, since it's the business code I want 100% coverage of, not the test code. Still I am curious if there is a way to compress multiple Exception throwing calls into one Testcase without having dead LoCs?

+4  A: 

Well, you can reduce it to a single dead line by extracting a utility method, e.g.

public void ExpectException<T>(Action action) where T : Exception
{
    try
    {
        action();
        Assert.Fail("Expected exception");
    }
    catch (T)
    {
        // Expected
    }
}

Call it with:

ExpectException<ArgumentNullException>
    (() => controller.Foo(null, new SecondParameter());

(You wouldn't need to wrap it in an IDE, of course... the line length on SO is pretty short.)

Jon Skeet
+5  A: 

From release notes of NUnit 2.4.7 NUnit now includes the RowTest extension, written by Andreas Schlapsi, in it's extension assemblies. This extension allows you to write test methods that take arguments and to provide multiple sets of argument values using the RowAttribute. To use RowTest, your test must reference the nunit.framework.extensions assembly.

It adds to NUnit the RowTest feature from MbUnit.

You can than write something like:

[RowTest]
[Row(1, 2, 3)]
[Row(3, 4, 8, TestName="Special case")]
[Row(10, 10, 0, TestName="ExceptionTest1",
ExpectedException=typeof(ArgumentException), ExceptionMessage="x and y may not be equal.")]
[Row(1, 1, 0, TestName="ExceptionTest2",
ExpectedException=typeof(ArgumentException), ExceptionMessage="x and y may not be equal.")]
public void AddTest(int x, int y, int expectedSum)
{
  int sum = Sum(x, y);
  Assert.AreEqual(expectedSum, sum);
}

http://www.andreas-schlapsi.com/2008/03/31/nunit-247-includes-rowtest-extension/ The code is from source code for Nunit RowTestExtension at Google code

Petar Repac