Coder Perfect

How can I verify that an exception has been thrown with Assert?

Problem

How can I verify that an exception has been thrown using Assert (or another Test class)?

Asked by Alex

Solution #1

It appears that the ExpectedException attribute is applied to the test function for “Visual Studio Team Test.”

Here’s an example from the documentation: A Visual Studio Team Test Unit Testing Walkthrough

[TestMethod]
[ExpectedException(typeof(ArgumentException),
    "A userId of null was inappropriately allowed.")]
public void NullUserIdInConstructor()
{
   LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
}

Answered by Kevin Pullin

Solution #2

In most cases, your testing framework will provide a solution. However, if it isn’t flexible enough, you may always perform the following:

try {
    somethingThatShouldThrowAnException();
    Assert.Fail(); // If it gets to this line, no exception was thrown
} catch (GoodException) { }

This DOES NOT work for catching a basic Exception, as @Jonas points out:

try {
    somethingThatShouldThrowAnException();
    Assert.Fail(); // raises AssertionException
} catch (Exception) {
    // Catches the assertion exception, and the test passes
}

You must rethrow the Assert if you really must catch Exception. Fail(). However, this is a clue that you shouldn’t be writing this by hand; look into your test framework for alternatives, or see if you can throw a more significant exception to test for.

catch (AssertionException) { throw; }

You should be able to customize this technique to your preferences, including defining which exceptions to catch. If you’re just expecting a few types, end the catch blocks with:

} catch (GoodException) {
} catch (Exception) {
    // not the right kind of exception
    Assert.Fail();
}

Answered by ojrac

Solution #3

My preferred method for accomplishing this is to create a Throws method and utilize it in the same way as any other Assert method. Because.NET does not allow you to construct a static extension method, you won’t be able to use this method as if it were part of the built-in Assert class; instead, create a new class called MyAssert or something like. This is how the class looks:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace YourProject.Tests
{
    public static class MyAssert
    {
        public static void Throws<T>( Action func ) where T : Exception
        {
            var exceptionThrown = false;
            try
            {
                func.Invoke();
            }
            catch ( T )
            {
                exceptionThrown = true;
            }

            if ( !exceptionThrown )
            {
                throw new AssertFailedException(
                    String.Format("An exception of type {0} was expected, but not thrown", typeof(T))
                    );
            }
        }
    }
}

As a result, your unit test should look like this:

[TestMethod()]
public void ExceptionTest()
{
    String testStr = null;
    MyAssert.Throws<NullReferenceException>(() => testStr.ToUpper());
}

Which is much more similar to the rest of your unit test syntaxes in appearance and behavior.

Answered by Richiban

Solution #4

You can accomplish something like this with NUNIT:

Assert.Throws<ExpectedException>(() => methodToTest());

It’s also feasible to save the thrown exception and use it later to validate it:

ExpectedException ex = Assert.Throws<ExpectedException>(() => methodToTest());
Assert.AreEqual( "Expected message text.", ex.Message );
Assert.AreEqual( 5, ex.SomeNumber);

See: http://nunit.org/docs/2.5/exceptionAsserts.html

Answered by damir

Solution #5

If you’re using MSTest, which didn’t come with an ExpectedException attribute at first, you may do something like this:

try 
{
    SomeExceptionThrowingMethod()
    Assert.Fail("no exception thrown");
}
catch (Exception ex)
{
    Assert.IsTrue(ex is SpecificExceptionType);
}

Answered by Jon Limjap

Post is based on https://stackoverflow.com/questions/933613/how-do-i-use-assert-to-verify-that-an-exception-has-been-thrown