Handling TPL exceptions in MSTest unit tests


In the past couple of years TPL (Task Parallel Library) and language features it brought became more and more popular in the .NET community. One of the differences that stood up is the exception handling. Unhandled exceptions that are thrown by user code that is running inside a task are propagated back to the joining thread. To propagate all the exceptions back to the calling thread, the Task infrastructure wraps them in an AggregateException instance.

Now this is all clear and quite straight forward to manage. I will not go in the detail about this topic as you can find all of the necessary information on MSDN at http://msdn.microsoft.com/en-us/library/dd997415(v=vs.110).aspx.

Once I started writing unit tests for my async methods I found out that I can’t anymore use my usual technique.

In order to assert that a certain unit is throwing a certain exception in well determined circumstances, I always went for the ExpectedException attribute. To make it even clearer, I will make an example of usage.

Now imagine the following class:

We are going to write a test that will assert that in case of a null being passed as a parameter to this method call, the method should raise an ArgumentNullException.
In order to do so, consider the following code.

Once executed, this test will pass.
Now let’s write an async analog of the previous method.

If we now try to execute the following test, it will fail.

As we do know that our exception is wrapped in an AggregateException, it is expected our test to fail. How should we than test this kind of situations?

Building a new attribute

Wait, I really liked the ExpectedException attribute, I would like to have an attribute that will check if any of the aggregated exceptions are of the type I do expect.
After a quick search I hadn’t found anything that suites me. That was the moment the ExpectedAggregateExceptionAttribute was born.
I followed the pattern on which ExpectedException was made and this is what I came up with.

To cut it short, I do check if the thrown exception is of AggregateException type, and if so I do again check if any of the inner exceptions is of the requested type. In case this condition is not matched a new exception is thrown which will make your unit test fail.
If we now use our new attribute instead of the ExpectedExceptionAttribute this test will be successful.

In order to be sure that our new attribute is working properly I will make some other tests. First I do expect the unit test to fail in case no exception was thrown:

Mind that this test is not meant to pass (do not include it in your solution).
Also, if in the inner exceptions there is no expected exception type, the test should fail:

As both test failed, I can conclude this new attribute works as supposed. You can package it as you wish, in your own common library, in a new or existing custom testing library or in any of your projects.

Downloads and the source code

You can find the source code and the demo project on Github at this address here.

Happy unit testing!

Leave a Reply

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