One of the new features introduced in .NET 2.0 is the Event-based Asynchronous Pattern. A class that supports this will have one or more methods named MethodNameAsync. These methods often mirror synchronous versions, which perform the same operation on the current thread. The class may also have a MethodNameCompleted event and it may have a MethodNameAsyncCancel method.
The Event-Based Asynchronous Pattern is used several places in the .NET 2.0 Framework , and one example many might find familiar are the auto generated Web Service Proxy classes. For every web service method you get a async version, and an event fired when the async method call finishes. The data is returned as the event argument. Code like this is really nice to work with, and makes it really simple to make more responsive clients where all web service calls happens on a separate thread. The disadvantage with asynchronous code is that it’s harder to write unit tests for.
This is a problem I’ve faced many times, and I’ve seen several different solutions. Many of them involves sleeping the thread executing the test, while waiting for the data to come back so that you can do any assertions on the returned data. This has several disadvantages. You don’t now exactly how long the asynchronous call is going to take, so you need to sleep “long enough”. Having thread sleeps in your tests are going to (big surprise) make your test suite slow. Now matter how fast your service returns it data, you still have to wait for all thread sleeps before the test ends. This is really inefficient, and can really become a problem when you have a large test suite integrated into a build environment. Another problem is that this is an unreliable way to do your testing, as they might pass some times, while fail others (if the thread sleep isn’t long enough).
The best solution I’ve found to unit testing of asynchronous code is the ManualResetEvent class found in the System.Threading namespace. I’m no threading expert, and I’m not going to try to explain how the .NET threading model works, but I’ve included a little snippet from the MSDN documentation explaining what you can use the ManualResetEvent class for:
“ManualResetEvent allows threads to communicate with each other by signaling. Typically, this communication concerns a task which one thread must complete before other threads can proceed”.
This is exactly what we want. When the thread executing the unit test starts an asynchronous call we want to block the thread, and wait for a signal from the callback before we continue. This way we spend the minimal time needed waiting for a result from the async method call, and don’t have to depend on thread sleeping for synchronizing the test with the result from the async method. I’ve included a simple NUnit test for a web service offering basic arithmetic operations. It calls the async versions of the add and subtract methods, performs assertions both on the returned data, and check if the async call actually completed. The details on how to use the ManualResetEvent is included in the code sample beneath (check the comments).