When you’re writing a unit test to verify that an exception is thrown and you want to check the content of the error message, the ExpectionException attribute doesn’t do it.
This code (which you see a lot):
[TestMethod]
[ExpectedException(typeof(ValidationException), “Postcode must be provided”)]
publicvoid PostcodeIsNullOrWhitespace()
{
//etc.
}
– checks that an exception is thrown, and the test will pass if the exception is of type ValidationException. The second parameter of the ExpectedException attribute is the string that will be written in the MSTest output if the test fails, so this test is not checking the content of the exception message.
If you do want to test the exception message as well as the exception type, this utility method does it for you:
///<summary>
/// Runs the action statement and asserts that it causes an exception with the expected type and message
///</summary>
///<typeparam name=”TException”></typeparam>
///<param name=”action”></param>
///<param name=”expectedMessage”></param>
publicstaticvoid AssertRaisesException<TException>(Action action, string expectedMessage)
where TException : Exception
{
try
{
action();
Assert.Fail(“Call suceeded. Expected exception of type: {0} with message: {1}”.FormatWith(typeof(TException).Name, expectedMessage));
}
catch (Exception ex)
{
if (ex isAssertFailedException)
throw ex;
var exception = ex as TException;
Assert.IsNotNull(exception, “Expected exception of type: {0}, actual type: {1}”.FormatWith(typeof(TException).Name, ex.GetType().Name));
Assert.AreEqual(expectedMessage, exception.Message, “Expected message: {0}”.FormatWith(expectedMessage));
}
}
Usage:
[TestMethod]
[ExpectedException(typeof(ValidationException))]
publicvoid PostcodeIsNullOrWhitespace()
{
var postcode = “”;
AssertRaisesException<ValidationException>(() => ValidatePostcode(postcode), “Postcode must be provided”);
//etc.
}