How to Check for Exceptions in Unit Testing

by Larry Spencer Monday, July 25, 2011 11:41 AM

When unit-testing to verify that exceptions are being reported correctly, there are two ways to proceed. The built-in way is not well-known and what I like to call the right way is even less well-known.

Using the ExpectedException Attribute

If you want to verify that your test subject threw a certain exception, you can decorate the test method with the ExpectedException atribute thus:

public void GetUserGuid_UserNotFound()
    // Perform test.

That works as far as it goes, but it does not test the message that was part of the exception. For something as general as an InvalidOperationException, wouldn't you want to know that the user will get the correct message?

Using the InternalsVisibleTo Attribute to Test for a Specific Message

It's easy enough to test for a specific message by hard-coding the message in both the assembly under test and the unit-test assembly. A better technique, though, is to put the message in the test subject's Resources file and make it visible to the unit-testing assembly. Here's the step-by-step.

1. Add the message as a resource.

Right-click the project in Visual Studio and then click Properties.

Select the Resources tab. If necessary, confirm that you want to create a default Resources file.

Add a new string resource. For our example, let's say that you call it MyMessage. In the Value column, enter the message.


Note that the access modifier is Internal by default. That's a good thing and we want to keep it that way.

Save your work.

2. Discover your test assembly's public key.

Assuming you're writing production code, you are no doubt strong-naming your assemblies. For this technique to work, you must also strong-name your unit-testing assembly. (I don't usually bother with that, but here's a case where it's mandatory.) Once you've done that, you'll need to know the public key of the unit-test assembly. Here's how to get it.

Open a Visual Studio command prompt.

Navigate to the directory that contains the assembly under test (C:\something\test\bin\debug, for example).

Enter this command:

SN -Tp MyAssembly.Test.dll

You will get output that includes the public key. Copy it to the clipboard. (Note that you can't get by with just the public key token.)

3. Make your resource visible to your test project.

Open the AssemblyInfo.cs of the assembly under test.

Add an attribute like this one.

// This is *in* the main assembly's AssemblyInfo.cs
// and it *names* the test assembly.
[assembly:InternalsVisibleTo("MyAssembly.Test, PublicKey=002400000480000......151e1")]

That attribute makes the internal members of your assembly available to the unit-testing assembly.

4. Reference the resource in your test project.

Now, your unit test can be more precise:

// No longer applies: [ExpectedException(typeof(System.InvalidOperationException))]
public void GetUserGuid_UserNotFound()
    // Perform test here...
  catch (InvalidOperationException ex)
    // Access the 'internal' resource 
    // of the assembly under test!
  Assert.Fail("Should have thrown an InvalidOperationException.");


All | General

Add comment

About the Author

Larry Spencer

Larry Spencer develops software with the Microsoft .NET Framework for ScerIS, a document-management company in Sudbury, MA.