Welcome to MSDN Blogs Sign in | Join | Help

Pedro Silva's Blog

Development lead on Visual Studio Platform team focusing on the extensibility of Visual Studio.

Syndication

News

My name is Pedro Silva. I’m the development lead in the Visual Studio Platform team at Microsoft, working on VS Extensibility features, enabling VS extensions and the VS SDK.

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Testing When Exceptions Are Expected

Been thinking about and looking at unit testing a lot recently. And, one of the items that came up was how do you test for expected exceptions to make sure that they're being thrown correctly. So, I wrote of few tests that did just that and noticed how similar they were, so I decided to create a helper method that exposed this test for easy use in all of my tests. These examples are all using the unit test framework that's part of VSTS, but the concept could be used for other C# based unit test tools.

The method uses an anonymous delegate to allow the caller to provide the code that should throw the exception, and wraps all the exception handling and test validation around it in the helper. The following is the code for the exception testing method:

namespace BlogLibraryTests

{

    /// <summary>

    /// Helper class that provides methods for helping unit test development, like handling

    /// expected exceptions and serialization of classes.

    /// </summary>

    internal static class UnitTestHelper

    {

        #region Exception Handling Helpers

        public delegate void ExceptionTestDelegate();

 

        /// <summary>

        /// Tests method for an expected exception being thrown.

        /// </summary>

        /// <param name="del"></param>

        /// <param name="exception"></param>

        static public void TestException(ExceptionTestDelegate del, Type exception)

        {

            try

            {

                // Call the delegate, fail the test if it doesn't throw an exception.

                del();

                Assert.Fail("Test should have thrown exception " + exception.ToString() + ".");

            }

            catch (AssertFailedException)

            {

                // If it's a failed assert, then just rethrow because it's our failure above.

                throw;

            }

            catch (Exception e)

            {

                // Test that the method threw the exception that we were expecting.

                Assert.IsInstanceOfType(e, exception, "Exception is not of the expected type.", exception.ToString());

            }

        }

        #endregion

 

    }

}

The code above will ensure that an exception was actually thrown, or fail otherwise. And, if there was an exception, that it's the type of exception that we were expecting. Not an overly complex amount of code, but very repetitive for every method that you're testing that throws an exception.  

Then calling it is just a matter of providing a delegate with the code that should throw the exception and the expected exception type:

        /// <summary>

        ///A test for NamedElement (string)

        ///</summary>

        [TestMethod()]

        public void ConstructorTest()

        {

            // Test with valid name string.

            string expected = "Foo";

            string name = expected;

            NamedElement target = new NamedElement(name);

 

            Assert.AreEqual(target.Name, expected, "NamedElement(name) didn't initialize correctly.");

 

            // Test with null name string.

            UnitTestHelper.TestException(delegate() { target = new NamedElement(null); }, typeof(ArgumentNullException));

        }

As you can see it makes for compact test writing and makes it easy to create a bunch of tests that ensure that your code throws the appropriate exceptions. 

 

Published Monday, September 24, 2007 10:27 AM by PedroSilva

Filed under: ,

Comments

# Techy News Blog &raquo; Testing When Exceptions Are Expected @ Monday, September 24, 2007 2:55 PM

PingBack from http://www.artofbam.com/wordpress/?p=2531

Techy News Blog » Testing When Exceptions Are Expected

# re: Testing When Exceptions Are Expected @ Monday, September 24, 2007 7:45 PM

But how is this really different than the ExpectedException attribute that can be applied to test methods in unit tests?

Tom

# re: Testing When Exceptions Are Expected @ Tuesday, September 25, 2007 3:28 AM

Indeed doesn't seem to be much different since this is also only checking the type.

Gerben van Loon

# VSTS Links - 09/27/2007 @ Thursday, September 27, 2007 10:33 AM

The Teams WIT Tools Blog on Dashboard Creator - Part III. Mike Azocar on An Addendum... Ognjen Bajic...

Team System News

# re: Testing When Exceptions Are Expected @ Thursday, September 27, 2007 8:29 PM

Yes indeed similar to ExpectedException, but you can also write more validation in this method if you want to... especially if you are defining a bunch of custom exceptions for your application.

PedroSilva

# re: Testing When Exceptions Are Expected @ Tuesday, October 16, 2007 4:39 AM

There is one important difference. ExpectedException just ensures that an exception is thrown somewhere in your test method. It does not test WHERE it is thrown.

For example, you have a test method does some setup and then makes a call that throws ArgumentNullException. What if your test setup starts throwing ArgumentNullException? You'll be none the wiser...

Using Pedro's method ensures you are getting exactly what you expect, and only where you expect it.

Bernie

# re: Testing When Exceptions Are Expected @ Tuesday, October 16, 2007 4:47 AM

You can rewrite Pedro's method to use generics. I think this makes it easier to read at the call site:

UnitTestHelper.TestException<ArgumentNullException>(delegate() { target = new NamedElement(null); });

You could even call it ExpectException, and hey presto, it's self documenting.

Bernie

# re: Testing When Exceptions Are Expected @ Thursday, October 18, 2007 4:41 PM

Yes, that's right, thanks Bernie. The attribute only really tells that an exception was thrown in that test method... Not that it was thrown by the code that you were expecting to throw it.  And, I do like the generic part of it too.

PedroSilva

New Comments to this post are disabled
Page view tracker