Unit testing thread exceptions and cancellations

Hackered
Tuesday, April 8, 2014
by Sean McAlinden

When testing a method that calls out to services (mocked) that are async, we need to be able to test what happens if an exception is thrown on the awaited service thread or the awaited service thread is cancelled. There are a number of ways this can be achieved, I have seen some quite elaborate and complicated approaches. I believe the following is a fairly straight forward approach which allows for an easy to read, clean code approach to this issue. By making use of the TaskCompletionSource class, we can easily put the thread into a faulted or cancelled state:

public static class AsyncTestHelper
{
    public static Task SetCancelledOnThread()
    {
        var tcs = new TaskCompletionSource<Task>();
        tcs.SetCanceled();
        return tcs.Task;
    }

    public static Task SetExceptionOnThread() where T : Exception
    {
        var tcs = new TaskCompletionSource();
        tcs.SetException(Activator.CreateInstance<T>());
        return tcs.Task;
    }
}

Setup Mock to return a cancelled thread

[Test]
public async Task When_Thread_Is_Cancelled_On_Async_DoSomething_Method()
{
    var myService = new Mock<IMyService>();
    myService.Setup(x => x.Foo()).Returns(AsyncTestHelper.SetCancelledOnThread);
    // etc.
}

Setup Mock to return exception on thread

[Test]
public async Task When_Thread_Throws_Exception_On_Async_DoSomething_Method()
{
    var myService = new Mock<IMyService>();
    myService.Setup(x => x.Foo()).Returns(AsyncTestHelper.SetExceptionOnThread<MyException>);
    // etc.
}

Hope you find these useful.