user3418770
user3418770

Reputation: 29

Unit Testing of async methods .NET 4.0 style

I have library functions in the library that I developed that execute asynchronously. Description by example:

private void Init()
{
     // subscribe to method completion event
     myLib.CompletionEvent += myLib_CompletionEvent; 
}

private void MyButton1_Click(object sender, EventArgs e)
{
    // start execution of Func1 
    myLib.Func1(param1, param2);
}

the Func1 initiates some processing in the library and immediately returns.

The result is of the processing arrives to the client as an event through a delegate

void myLib_CompletionEvent(ActionResult ar)
{
    // ar object contains all the results: success/failure flag 
    // and error message in the case of failure.
    Debug.Write(String.Format("Success: {0}", ar.success);
}

So here is the question: How do I write Unit test for this?

Upvotes: 1

Views: 227

Answers (1)

NeddySpaghetti
NeddySpaghetti

Reputation: 13495

I'd recommend creating a task based asynchronous method using a TaskCompletionSource and then using the support for async\await by testing frameworks such as MsTest and Nunit to write an asynchronous unit test. The test must be marked as async and is usually required to return a Task

You can write the asynchronous method like this(untested):

public Task Func1Async(object param1, object param2)
{
   var tcs = new TaskCompletionSource<object>();

    myLib.CompletionEvent += (r => 
    {
        Debug.Write(String.Format("Success: {0}", ar.success));

        // if failure, get exception from r, which is of type ActionResult and 
        // set the exception on the TaskCompletionSource via tcs.SetException(e)

        // if success set the result
        tcs.SetResult(null);
    });

    // call the asynchronous function, which returns immediately
    myLib.Func1(param1, param2);

    //return the task associated with the TaskCompletionSource
    return tcs.Task;
}

Then you can write your test like this:

    [TestMethod]
    public async Task Test()
    {
         var param1 = //..
         var param2 = //..

         await Func1Async(param1, param2);

         //The rest of the method gets executed once Func1Async completes

         //Assert on something...
    }

Upvotes: 1

Related Questions