Await a Async Void method call for unit testing

mocking async methods c#
xunit async void
async test method must have non-void return type
xunit async tests
c# unit test async task
unit test async method c# nunit
unit test async/await javascript
async void methods are not supported, please use 'async task' instead

I have a method that looks like this:

private async void DoStuff(long idToLookUp)
{
    IOrder order = await orderService.LookUpIdAsync(idToLookUp);   

    // Close the search
    IsSearchShowing = false;
}    

//Other stuff in case you want to see it
public DelegateCommand<long> DoLookupCommand{ get; set; }
ViewModel()
{
     DoLookupCommand= new DelegateCommand<long>(DoStuff);
}    

I am trying to unit test it like this:

[TestMethod]
public void TestDoStuff()
{
    //+ Arrange
    myViewModel.IsSearchShowing = true;

    // container is my Unity container and it setup in the init method.
    container.Resolve<IOrderService>().Returns(orderService);
    orderService = Substitute.For<IOrderService>();
    orderService.LookUpIdAsync(Arg.Any<long>())
                .Returns(new Task<IOrder>(() => null));

    //+ Act
    myViewModel.DoLookupCommand.Execute(0);

    //+ Assert
    myViewModel.IsSearchShowing.Should().BeFalse();
}

My assert is called before I get done with the mocked up LookUpIdAsync. In my normal code, that is just what I want. But for my Unit test I don't want that.

I am converting to Async/Await from using BackgroundWorker. With background worker this was functioning correctly because I could wait for the BackgroundWorker to finish.

But there does not seem to be a way to wait for a async void method...

How can I unit test this method?

You should avoid async void. Only use async void for event handlers. DelegateCommand is (logically) an event handler, so you can do it like this:

// Use [InternalsVisibleTo] to share internal methods with the unit test project.
internal async Task DoLookupCommandImpl(long idToLookUp)
{
  IOrder order = await orderService.LookUpIdAsync(idToLookUp);   

  // Close the search
  IsSearchShowing = false;
}

private async void DoStuff(long idToLookUp)
{
  await DoLookupCommandImpl(idToLookup);
}

and unit test it as:

[TestMethod]
public async Task TestDoStuff()
{
  //+ Arrange
  myViewModel.IsSearchShowing = true;

  // container is my Unity container and it setup in the init method.
  container.Resolve<IOrderService>().Returns(orderService);
  orderService = Substitute.For<IOrderService>();
  orderService.LookUpIdAsync(Arg.Any<long>())
              .Returns(new Task<IOrder>(() => null));

  //+ Act
  await myViewModel.DoLookupCommandImpl(0);

  //+ Assert
  myViewModel.IsSearchShowing.Should().BeFalse();
}

My recommended answer is above. But if you really want to test an async void method, you can do so with my AsyncEx library:

[TestMethod]
public void TestDoStuff()
{
  AsyncContext.Run(() =>
  {
    //+ Arrange
    myViewModel.IsSearchShowing = true;

    // container is my Unity container and it setup in the init method.
    container.Resolve<IOrderService>().Returns(orderService);
    orderService = Substitute.For<IOrderService>();
    orderService.LookUpIdAsync(Arg.Any<long>())
                .Returns(new Task<IOrder>(() => null));

    //+ Act
    myViewModel.DoLookupCommand.Execute(0);
  });

  //+ Assert
  myViewModel.IsSearchShowing.Should().BeFalse();
}

But this solution changes the SynchronizationContext for your view model during its lifetime.

Async Programming, Unit Testing Async Code I'd like to look briefly at how to unit test async code. write good tests that call async methods, depending on support from your unit [​TestMethod] public async void AlexsTest () { int x = await AlexsMethod (); Assert . Unit test frameworks are converging away from async void unit tests and toward async task unit tests. If you have any async void unit tests, I recommend you change them today to async task unit tests. I expect over the next couple years you’ll see much better support for testing failure cases in async unit tests.

An async void method is essentially a "fire and forget" method. There is no means of getting back a completion event (without an external event, etc).

If you need to unit test this, I would recommend making it an async Task method instead. You can then call Wait() on the results, which will notify you when the method completes.

However, this test method as written would still not work, as you're not actually testing DoStuff directly, but rather testing a DelegateCommand which wraps it. You would need to test this method directly.

11. Unit Testing Async Code - Async in C# 5.0 [Book], You can declare an async void method, but this should be used only for event instead of int in synchronous method (look at my previous post Unit Testing C# The async method being tested is called via await operator. In order to use await in a unit test method, the test itself has to be declared with async in its signature. No sleep statement is needed anymore: [Test] public async Task SynchronizeTestWithCodeViaAwait() { var sut = new SystemUnderTest(); // Schedule operation to run asynchronously and wait until it is finished.

I figured out a way to do it for unit testing:

[TestMethod]
public void TestDoStuff()
{
    //+ Arrange
    myViewModel.IsSearchShowing = true;

    // container is my Unity container and it setup in the init method.
    container.Resolve<IOrderService>().Returns(orderService);
    orderService = Substitute.For<IOrderService>();

    var lookupTask = Task<IOrder>.Factory.StartNew(() =>
                                  {
                                      return new Order();
                                  });

    orderService.LookUpIdAsync(Arg.Any<long>()).Returns(lookupTask);

    //+ Act
    myViewModel.DoLookupCommand.Execute(0);
    lookupTask.Wait();

    //+ Assert
    myViewModel.IsSearchShowing.Should().BeFalse();
}

The key here is that because I am unit testing I can substitute in the task I want to have my async call (inside my async void) to return. I then just make sure the task has completed before I move on.

Unit Testing C# Async Methods – Andrey Zavadskiy – SQL and .NET , Here's the updated unit test method that takes advantage of await to call the asynchronous method: [TestMethod] It is quite difficult to retrieve the result of async void unit tests and hence they should be avoided. Unlike async  This SO answer provides some insight as to why async void won't work in unit tests – devNull Mar 11 '19 at 17:43 Console result = System.Threading.Tasks.Task'1{System.Web.Http.IHttoActionResult ] so far – usertestREACT Mar 11 '19 at 19:02

The only way I know is to turn your async void method to async Task method

My two cents on unit testing asynchronous code, Visual Studio 2012 will support asynchronous unit tests, as long as those tests are Note that async void methods interact with SynchronizationContext in a in some cases so their original call stack is preserved appropriately, and if with all the benefits of async/await, and the async context takes care of  This would require our test method to be async. Congratulations, you can move on to the next section. Wrong Way #2: Using Async Test Methods. This mistake is more common for people who have used async in some real-world code. They’ve observed how async “grows” through the code base, and so it’s natural to extend async to the test methods.

You can use an AutoResetEvent to halt the test method until the async call completes:

[TestMethod()]
public void Async_Test()
{
    TypeToTest target = new TypeToTest();
    AutoResetEvent AsyncCallComplete = new AutoResetEvent(false);
    SuccessResponse SuccessResult = null;
    Exception FailureResult = null;

    target.AsyncMethodToTest(
        (SuccessResponse response) =>
        {
            SuccessResult = response;
            AsyncCallComplete.Set();
        },
        (Exception ex) =>
        {
            FailureResult = ex;
            AsyncCallComplete.Set();
        }
    );

    // Wait until either async results signal completion.
    AsyncCallComplete.WaitOne();
    Assert.AreEqual(null, FailureResult);
}

Async Unit Tests, Part 2: The Right Way, In short, exceptions thrown when calling an async void method isn't If you write unit tests using XUnit. Subscribe(async _ => await Task. I'm having some problems unit testing async methods. Here's my unit test code: [TestMethod] public async Task TestRefreshList_RefreshesList() { int countBeforeAdd = listViewModel.NotesTitles.Count; // Add a note. await listViewModel.NoteRepository.AddNoteAsync(new Note { Title = String.Empty, Content = String.Empty }); // Refresh.

Avoid async void methods, There are a few quirks when we're testing asynchronous methods. Instead of simply calling the "GetPeople" method, we should "await" it. frameworks (just remember to return "Task" instead of "void" on the test methods). xUnit.NET has recently released first-class support for asynchronous unit tests: in version 1.9 (2012-01-02) and newer, for any test method returning Task/Task<T>, the test framework will wait until the task completes before declaring success/failure. However, as of now, it does not support async void unit tests; this is planned for a future

More DI: Unit Testing Async Methods, Previously, when testing asynchronous methods such as the one below, I used public async void TestSuccessAwait() If you make your test method async and await the call to the method under test, you Further reading : https://blog.​stephencleary.com/2012/02/async-unit-tests-part-1-wrong-way.html  Because the test method is async void, any exceptions that happen in it are rethrown on the calling SynchronizationContext, where they are either ignored, or cause an unrelated future test to fail. The real danger here is that all your tests will appear to pass, irrespective of the actual result. Writing Working Async Tests Manually

Testing Async Methods with Xunit, Recently, my team and I started writing unit tests on an application that an async void method will return immediately on the first await , so NUnit will task is awaited), NUnit calls the WaitForPendingOperationsToComplete  When you call an async void method, you cannot await it because the await keyword is applicable on a Task, not on a method that returns nothing. From the C# reference on await, The task to which the await operator is applied typically is returned by a call to a method that implements the Task-Based Asynchronous Pattern.

Comments
  • This would work. But I would rather not have to have two methods for all my async voids. I figured a way to do it (at least in my case). See my answer on this question if you are interested.
  • Nice - you've created the C# predecessor of github.com/btford/zone.js ZoneJS.
  • What is the benefit of awaiting DoLookupCommandImpl(idToLookup) in DoStuff(long idToLookUp)? What if it would be called without awaiting?
  • @jacekbe: awaiting the task observes exceptions; if you call it without await, then any failures are silently ignored.
  • I can't change it to return Task because the DelegateCommand will not allow that.
  • Having a unit test scaffolding around my code is very important. I may have to make all (important) "async void" methods use BackgroundWorker if they can't be unit tested.
  • @Vaccano The same thing would happen with BackgroundWorker - you just need to make this an async Task instead of async void, and wait on the task...
  • @Vaccano You should have no async void methods (except for event handlers). If an exception is raised in async void method, how are you going to handle it?
  • I figured out a way to make it work (at least for this case). See my answer on this question if you are interested.
  • Just because your lookupTask has finished, doesn't mean the method under test (DoStuff? or DoLookupCommand?) has finished running. There is a small chance that the task has finished running, but IsSearchShowing hasn't been set to false yet, in which case your assertion would fail.
  • An easy way to prove this would be to put Thread.Sleep(2000) before setting IsSearchShowing to false.
  • any AsyncMethodToTest class sample ?
  • Why not just use Wait() ?
  • what is configuration ?
  • @Dementic An example? Or more specific an instance of an object with a member InitializeAsync that returns a task.