How do I test an async method with NUnit (or possibly with another framework)?

Bear in mind that the NUnit 2.6 series, like those before it, is built to target the .NET 2.0 framework. So, NUnit can only do the same things you could code yourself, in an assembly targeting .NET 2.0.

Specifically, you can't mark your test method as async and expect NUnit to do anything special with it.

You can, however,

  • Target .NET 4.5 for your tests. NUnit will run them in a separate process.
  • Use await in your test to wait for the result of a call to an async method.

Neither of the above will give you asynchronous test execution, if that's what you are hoping for. No other tests will execute while waiting for the asynchronous operation to complete.

Another option is to use NUnitLite. NUnitLite 0.8 supports the [Asynchronous] attribute which will allow other tests to continue while your asynchronous test completes. The advantage of the attribute is that it allows asynchronous tests to work in .NET 2.0 through 4.0

We don't currently have a .NET 4.5 build of NUnitLite but it will be added soon and we are working on a change that will make use of [Asynchronous] optional in that environment. For now, you can easily download and recompile the source code for .NET 4.5.

For the future, look to NUnit 3.0 to support async methods fully along with general parallel execution of tests on multiple threads or in multiple processes.


It seems to me there is no support built into NUnit 2.6 for testing async methods returning Tasks. The best option I can see right now is to use Visual Studio's own UnitTesting framework or xUnit.net as both support asynchronous tests.

With the Visual Studio UnitTesting framework I can write asynchronous tests like this:

using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class TestAsyncMethods
{
    [TestMethod]
    public async Task TestGetBinBuildById()
    {
         ...
         var rslt = await obj.GetAsync();
         Assert.AreEqual(rslt, expected);
    }
}

As of today (7/2/2014) async testing is supported by:

  • xUnit: with async methods that return a Task (since 1.9)
  • MSTest: with async methods that return a Task (since VS 2012)
  • NUnit: with async methods that return a Task, or even, that return void, since 2.6.2. Since 3.0 th option to return void is not supported, as the doc of the analyzer error NUnit1012 The async test method must have a non-void return type explains.

In the first two frameworks, the test method must have this signature:

[TestMethod]
public async Task MyTestMethod()
{
   ...
   var result = await objectUnderTest.TestedAsyncMethod(...);
   // Make assertions
}

NUnit v2.6.2+ (but before 3.0), apart from that signature, supports this one:

public async void MyTestMethod()

Of course, inside any of these test methods you can use await to call and wait on asynchronous methods.

If you're using a testing framework that doesn't support async test methods, then, the only way to do it, is to call the async method and wait until it finishes running using any of the usual ways: await, reading the Result property of the Task<T> returned by an async method, using any of the usual wait methods of Task and so on. After the awaiting, you can do all the asserts as usual. For example, using MSTest:

[TestMethod]
public void MyTestMethod()
{
    ...
    Task<MyResultClass> task = objectUnderTest.MyAsyncMethod(...);
    // Make anything that waits for the method to end
    MyResultClass result = task.Result;

    // Make the assertions
    Assert.IsNotNull(result);
    ...
}

I'm in the process of converting some of my methods to async. Getting this to work with NUnit has been quite straightforward.

The test methods can not be asynchronous. But we still have access to the full functionality of the Task Parallel Library, we just can't use the await keyword directly in the test method.

In my example, I had a method:

public string SendUpdateRequestToPlayer(long playerId)

And it was tested in NUnit like so:

string result = mgr.SendUpdateRequestToPlayer(player.Id.Value);
Assert.AreEqual("Status update request sent", result);
mocks.VerifyAll();

Now that I have altered the method SendUpdateRequestToPlayer to be asynchronous

public async Task<string> SendUpdateRequestToPlayer(long playerId)

I simply had to modify my tests to Wait for the task to complete:

Task<string> task = mgr.SendUpdateRequestToPlayer(player.Id.Value);
task.Wait(); // The task runs to completion on a background thread
Assert.AreEqual("Status update request sent", task.Result);
mocks.VerifyAll();