How to test an async void method

async-await, c#, unit-testing

Solution

The simple answer here is: don't make it an `async void`. In fact, don't ever make something an `async void` unless it absolutely has to be to work as an event-handler. The things that `async void` loses are precisely the things that you want here for your test (and presumably for your real code).

Make it an `async Task` method instead, and you now have the ability to wait for completion (with timeout) / add a continuation, and to check whether it exited with success or an exception.

This is a single word change, to:

public async Task GetBrands()
{
    // ......

    Brands = await _dataHelper.GetFavoriteBrands();

    // ......
}

and then in the test:

[TestMethod]
public async Task AllBrandsTest()
{
    BrandsViewModel viewModel = new BrandsViewModel();
    var task = viewModel.GetBrands();
    Assert.IsTrue(task.Wait(YOUR_TIMEOUT), "failed to load in time");
    Assert.IsTrue(viewModel.Brands.Any(), "no brands");
}

Problem

Please consider the code as shown below. By calling GetBrands, property Brands will be assigned with proper data. ``` public class BrandsViewModel : ViewModelBase { private IEnumerable<Brand> _brands; public IEnumerable<Brand> Brands { get { return _brands; } set { SetProperty(ref _brands, value); } } public async void GetBrands() { // ...... Brands = await _dataHelper.GetFavoriteBrands(); // ...... } } ``` But if I test it as shown below, the test failed. How do I wait for the async call inside method GetBrands? ``` [TestMethod] public void AllBrandsTest() { BrandsViewModel viewModel = new BrandsViewModel(); viewModel.GetBrands(); Assert.IsTrue(viewModel.Brands.Any()); } ```

Original source