The Grayzone

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);
}

Share this: