Unit-testing – Unit testing invalid inputs; ArgumentException vs. Custom Exception

exceptionsunit testing

In unit tested code I often have multiple checks on the arguments on any method before the actual "work" of the method is begun:

public void DoSomething(string test)
{
   if (string.IsNullEmptyOrWhiteSpace(test))
   {
       throw new ArgumentException("Test must not be empty", "test");
   }
}

In my corresponding test for this method I'll do the following:

[Test]
[ExpectedException(typeof(ArgumentException),
    Message = "Parameter name: test",
    MatchType = MatchType.Contains)]
public void TestNullInput()
{
    var classToTest = new ClassToTest();
    classToTest.DoSomething(null);
}

I'm thinking that this is quite a bad way to go about doing the test, however, as it relies on a specific named parameter (which does not necessarily hold true after any refactoring), as well as the format of the message of an ArgumentException.

Another option might be to create a custom exception for this, some form of "TestWasNullOrEmptyException", but this also seems fairly awkward, as there will be many many different exceptions throughout the solution, each used to indicate only the absence/invalidity of a parameter.

I am wondering if anyone else has dealt with this issue, and whether I'm simply going about my input validation tests the wrong way of it there's a more elegant solution.

EDIT: This is C# code, and I'm using NUnit/Rhino Mocks.

Best Answer

What test framework are you using? Looks similar to junit (ExpectedException, MatchType), but the square bracket syntax is new to me. Is this c#'s NUNIT?

I use junit 4's ExpectedException in a programatic way. Therefore, I can set a lot of attributes of the Exception, like thrown.expectMessage(startsWith("What"));. For me, this is sufficiently flexible.

Another option might be to create a custom exception for this, some form of "TestWasNullOrEmptyException"

That does not seem to be good idea. With that argument, you could never use a general exception. But abstraction is good, to cope with complexity. In your case, thousands of new Exception classes, that also have to be caught and handled somewhere, would produce the complexity that can better be dealt with via more abstract exceptions, like ArgumentException.

Related Topic