Making sure asynchronous unit tests don’t cause a deadlock
In my previous blog post I wrote about creating asynchronous unit tests for Silverlight using the Microsoft Silverlight Unit Test Framework. This asynchronous testing capability that the Microsoft Silverlight Unit Test Framework has in the box lets us create some pretty advanced testing capabilities.
The problem with asynchronous tests.
While the async test pattern is very powerful it also has a drawback. This drawback is that the EnqueueTestComplete() must be executed or the test will never complete and the whole test run will halt. And while the test runner will tell you which test is executing it will not tell you where it is waiting, all it does is just sit there and wait.
Take the following test for example. Because the EnqueueConditional() action always returns false it is never going to end.
[TestMethod]
[Asynchronous]
public void TestThatNeverFinishes()
{
// Do some asynchronous work
EnqueueConditional(() => false);
EnqueueTestComplete();
}
Now a Timeout attribute telling the Microsoft Silverlight Unit Test Framework to abort the test if it takes longer than a predefined amount of time would be nice. In fact there is even a Timeout attribute as part of the Microsoft.VisualStudio.TestTools.UnitTesting namespace but adding the Timeout attribute to a SilverlightTest has no effect 
The solution
The solution is not very difficult but it does mean having to check for the timeout ourselves. In fact just adding an Assert to every EnqueueConditional() to make sure we don’t timeout will do the trick just fine. The only downside is that we have to do so in very check. If we change the test to the following the test will timeout, with an error, if it takes to long.
[TestMethod]
[Asynchronous]
public void TestThatNeverFinishes()
{
DateTime startTime = DateTime.Now;
// Do some asynchronous work
EnqueueConditional(() =>
{
Assert.IsTrue((DateTime.Now - startTime) < TimeSpan.FromSeconds(10),
"Timeout on condition 'return false;'");
return false;
});
EnqueueTestComplete();
}
The result is a “nice” error indicating the test took too long.
Nice, now if only the Microsoft Silverlight Unit Test Framework would support the Timeout attribute it would be even better.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu