Mark Gilbert's Blog

Science and technology, served light and fluffy.

Unit Testing for Exceptions

This is the first in a two-part series on unit testing.  I’ll be covering the structures that I use in my unit tests for custom exceptions and events.

The basic idea for exceptions is that I do something in the unit test that should cause an exception to be thrown, and then wrap that code in a Try..Catch block to check that it IS thrown.

<Test()> _

Public Sub Save_WeightNotNumeric_CorrectExceptionThrown()

    Dim MyObject As MyClass

    Dim WasCorrectExceptionThrown As Boolean

    Dim ExceptionText As String

 

    WasCorrectExceptionThrown = False

    ExceptionText = “{exception text was not set}”

 

    Try

        MyObject = New MyClass

        MyObject.Save

    Catch ex As MyClass.InvalidDataException

        WasCorrectExceptionThrown = True

        ExceptionText = ex.Message

    Catch ex As Exception

        WasCorrectExceptionThrown = False

        ExceptionText = ex.Message

    End Try

 

    Assert.IsTrue(WasCorrectExceptionThrown, “Expected exception was not thrown; this one was: “ & ExceptionText)

    Assert.IsTrue(ExceptionText.Contains(“field ‘Weight'”), “Exception thrown did not mention the correct field: “ & ExceptionText)

End Sub

The first Catch block looks for the exception that I’m expecting to be thrown, and sets WasCorrectExceptionThrown to True when it executes.  I then include a second Catch block that handles any other exceptions thrown.  In both cases I also save off the exception text for use in the Asserts.

The assertions look for two things – did the correct exception get thrown, and did that exception have the appropriate message*.  The second of these two assertions will vary greatly depending on the particular needs of the test, and in many cases may not be needed at all.

Notice also that I set the ExceptionText variable to a known value before starting – “{exception text was not set}”.  This allows the first assertion to cover both the case where the wrong (well, ok, the “expected”) exception was thrown as well as the case were no exception was thrown.  I can see which case occurred based on the error message that appears in NUnit.

NUnit does provide an ExpectedExceptionAttribute (see http://www.nunit.org/index.php?p=exception&r=2.2.10 for more information), but that only allows the test to see if the correct exception was thrown.  So far as I can tell there isn’t a way to inspect the message that comes back to make sure that it’s correct.

Next we’ll look at testing for custom events.

 

*You might ask “Mark, why are you passing information back in the message?  If you’re going to go to the trouble to build custom exceptions, why not build a new custom exception for every exceptional case?”  In a lot of cases I do, but in the cases where I am validating a slew of input parameters before doing some processing and I want to communicate when one doesn’t contain valid data, I’ll throw something like an InvalidDataException, and pass back the name of the field that was invalid.  I tend to be lazy and will write these messages to be appropriate for the user, so class that catches the exception can simply clean up what it needs to based on the type of exception thrown and then pass the message back to the UI unmodified.

Advertisements

July 6, 2009 - Posted by | Agile, Visual Studio/.NET

Sorry, the comment form is closed at this time.

%d bloggers like this: