ExceptionAssert.Throws instead of ExpectedException

Jimmy Bogard has already written about the perils of using the ExpectedException attribute in unit testing (MS Test and NUnit have that attribute). NUnit has dealt with this by including an Assert.Throws<T> method (it also has an Assert.Catch<T> method).

My testing framework of choice (MS Test) does not have an equivalent (disappointing). So, I set about writing one. The implementation looks like this:

public static class ExceptionAssert
{
        public static void Throws<T>(Action code, string exceptionMessage = null, string message = null, params object[] args) where T : Exception
        {
            try
            {
                code.Invoke();

                Assert.Fail("No exception was thrown by the code under test.");
            }
            catch (Exception exception)
            {
                if (string.IsNullOrWhiteSpace(exceptionMessage))
                {
                    Assert.AreEqual(exception.GetType(), typeof(T), message, args);
                }
                else
                {
                    Assert.AreEqual(exception.GetType(), typeof(T), message, args);
                    Assert.IsTrue(exception.Message.StartsWith(exceptionMessage, StringComparison.OrdinalIgnoreCase));
                }
            }
        }
}

And using it in a unit test as so:

[TestMethod]
[TestCategory(TestCategories.MembershipIntegration)]
public void CreateUserAccountWithNoTenantThrowsException()
{
	var membershipService = new MembershipService();

	ExceptionAssert.Throws<ArgumentNullException>(
		() =>
			membershipService.CreateUser(null, 
			TestFirstName, 
			TestLastName, 
			TestFirstName + " " + TestLastName,
			TestPassword, TestEmail
			));
}

Now, we won’t get the false negative in the event that the exception is thrown in the constructor of the MembershipService class, rather than in the method under test, membershipService.CreateUser.

If you want to verify the text of the exception message, you can do that too:

[TestMethod]
[TestCategory(TestCategories.MembershipIntegration)]
public void CreateUserAccountWithNoTenantThrowsException()
{
	var membershipService = new MembershipService();

	ExceptionAssert.Throws<ArgumentNullException>(
		() =>
			membershipService.CreateUser(null, 
			TestFirstName, 
			TestLastName, 
			TestFirstName + " " + TestLastName,
			TestPassword, TestEmail
			),
			"The argument was null"
			);
}

I’ve also included parameters for a failure message and formatting of that message (which is a normal overload of the Assert methods).

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>