MSTest Custom Assert for Exceptions

With MSTest is it common to use the ExpectedException Attribute to test for a certain exception thrown. Since you typically want to test one, and only one, aspect in a unit test, the ExpectedException attribute can cause some unexpected behaviors. In the code below there is no way of telling if the exception was thrown while calling the Add method of the TodoService. This might as well occur while arranging the TodoItem or TodoService. It also looks as if there’s no assertion in this testmethod.

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void ServiceShouldThrowExeptionWhenTodoItemIsNull()
{
    // Arrange
    var todoItems = new List<TodoItem>();
    var todoService = new TodoService(todoItems);

    // Act
    todoService.Add(todoItem: null);

    // Assert ???
}

With custom code we can change that to something more in line with Assert.Throws or Record.Exception in xUnit.

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

namespace Remondo.Common.Testing
{
    internal class CustomAssert
    {
        public static void IsThrown<T>(Action action) where T : Exception
        {
            try
            {
                action.Invoke();

                Assert.Fail("Exception of type {0} should be thrown.", typeof (T));
            }
            catch (Exception exc)
            {
                Assert.IsInstanceOfType(exc, typeof (T));
            }
        }
    }
}

Using this custom assert, we know for sure the exception was thrown while acting on the Add method of the service and not while arranging. The only thing I do not like is the combined Act and Assert sections.

[TestMethod]
public void ServiceShouldThrowExeptionWhenTodoItemIsNull()
{
    // Arrange
    var todoItems = new List<TodoItem>();
    var todoService = new TodoService(todoItems);

    // Act & Assert
    CustomAssert.IsThrown<NullReferenceException>(
        () => todoService.Add(todoItem: null));
}

It is also possible to use xUnit asserts in MSTest Richard Banks shows in How to Add Assert.Throws() to MSTest.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

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