How do you await a Task when unit testing?

In a C# testing project, I have this test:

[TestMethod]
public void TestIfListFilled()
{
    // arrange
    byte stuffTypeID = 0;
    List<Stuff> locationList = null;

    // act
    locationList = GetStuffListAsync(stuffTypeID);

    // assert
    Assert.IsTrue(locationList.Count > 0);
}

And the GetStuffListAsync method has this signature:

Task<List<Stuff>> GetStuffListAsync(Byte stuffTypeID)

Now, my first guess was to add an await before the method call in my test method. However, I can't add async to my testmethod's signature, or Visual Studio will start complaining. What can I do to get my list filled before the assertion is performed?

Jon Skeet
people
quotationmark

You can make your unit test async as well:

[TestMethod]
public async Task TestIfListFilled()
{
    // arrange
    byte stuffTypeID = 0;

    // act
    List<Stuff> locationList = await GetStuffListAsync(stuffTypeID );

    // assert
    Assert.IsTrue(locationList.Count > 0);
}

Note that using Result instead could easily cause a deadlock, depending on the synchronization context your test runner has set up; you could end up with the async method's continuation waiting to get back onto a thread which is waiting for the async method to complete.

Note the change of the return type to Task - this may be used by the unit test runner to detect completion in a cleaner way than the alternatives, and it's also useful to make sure that the test will break if you try to run it in a test runner which doesn't support async tests.

If you want more control over how your underlying async operations work, it's possible to install your own synchronization context and creating tasks (to be returned by dependency fakes) which will only complete after you've stepped appropriately. It gets very complicated, but it's feasible - I have some sample code somewhere, but not handy...

people

See more on this question at Stackoverflow