1

I have some tests that run through the workflow of my WPF program. I do the normal MVVM approach which is binding buttons on the view to commands on the view model, which then handles the event. The way my tests test my workflow is then by directly executing the commands on the view model. This roughly translates to look something like:

[Test]
public void Test()
{
    var vm = new ViewModel();
    vm.AcceptCommand.Execute();
    Assert.IsTrue(stuff);
}

All of this works well, except for the fact that the code in the viewmodel that handles the command ends up being an async void method since this just becomes an event handler. If an exception gets thrown here, nunit does not show a failing test because it doesn't "see" this exception in the background thread.

My question is: is there a way to get NUnit to handle these background exceptions?

Artem
  • 2,084
  • 2
  • 21
  • 29
ptsoccer
  • 158
  • 6

2 Answers2

2

There is a separate method in NUnit to verify exceptions in async methods:

var exception = Assert.ThrowsAsync<NotImplementedException>(() => vm.AcceptCommand.Execute());

or vice versa:

Assert.DoesNotThrowAsync(() => vm.AcceptCommand.Execute());
Artem
  • 2,084
  • 2
  • 21
  • 29
  • This does not work in my case since the event handler is async void so the exception "escapes" the nunit context – ptsoccer Jul 04 '17 at 00:12
1

If it's possible then refactor your method into 2 methods. First one should return Task and it's the one that is testable. The other should call and await first method. This hint is taken from Concurrency in C# Cookbook by Stephen Cleary. This is the preferred method. This book also mentions AsyncContext class from AsyncEx library which allows to test async void methods.

AsyncContext.Run(() =>
 { 
     // put your code here
 })

Quote from the same book: The AsyncContext type will wait until all asynchronous operations complete (including async void methods) and will propagate exceptions that they raise.

Take a look here for similar discussion: Await a Async Void method call for unit testing

jacekbe
  • 499
  • 1
  • 5
  • 18
  • In my case, calling a different method during test isn't always possible since many of my tests execute at a higher level and won't be able call a different method (since it won't be the one making the call). I also dislike the fact that this isn't automatic, as in I (or anyone else working on the project) has to remember to do this special thing. The AsyncContext is intriguing though, I will investigate that the next chance I get. – ptsoccer Jul 04 '17 at 00:17