Unit Testing Asynchronous Operations
The Problem
I’m currently working on an application that uses the MapPoint 2010 API to generate routing data. Some of the operations can be quite long-running (often < 20s but some can run up to a couple of mins). Due to this I use a BackgroundWorker in my main class to process each route’s data. I ran into some problems unit testing this since it is an asynchronous process but I found a solution, not necessarily the cleanest but it works.
The Solution
In the end the solution was quite simple. I had to figure a way of making the thread wait until the “CalculationComplete” event is raised. To do this I used the ManualResetEvent class. I can then use the ManualResetEvent.WaitOne() method to tell the current thread to wait until it receives notification. Notification is then sent using the ManualResetEvent.Set() event, called from the completed event of the asynchronous method being tested.
For this example I will use a class called “CalculateData” which has a “CalculationComplete” event and a method called “StartCalculationAsync”.
[TestMethod]
public void Test_Calculation()
{
// Instantiate class to test
CalculateData calcData = new CalculateData();
// Instantiate ManualResetEvent, setting to unsignalled
ManualResetEvent eventCompletion = new ManualResetEvent(false);
// Variable to store return args
CustomEventArgs eventArgs = null;
// Use an anonymous function to set value of eventArgs and signal to ManualResetEvent to continue
calcData.CalculationComplete += (sender, e) =>
{
eventArgs = e;
// Call set method to signal thread to continue
eventCompletion.Set();
};
// Call async method to be tested
calcData.StartCalculationAsync(arg1, arg2);
// Signal thread to wait here until signal received
eventCompletion.WaitOne();
// Assert statement will be reached once completion event raised.
Assert.IsFalse(eventArgs.boolProperty);
}