Test property set by async method

I am trying to test a class using NUnit, which contains async methods. I do not know how to do it right.

I have a class that looks like this:

public class EditorViewModel:INotifyPropertyChanged { public void SetIdentifier(string identifier) { CalcContentAsync(); } private async void CalcContentAsync() { await SetContentAsync(); DoSomething(); } private async Task SetContentAsync() { Content = await Task.Run<object>(() => CalculateContent()); RaisePropertyChanged("Content"); } public object Content { get; private set; } ... } 

How can I write a test in NUnit that checks that the Content-Property is set to the correct value? I want to do something like this:

 [Test] public void Content_WhenModifierIsXXX_ReturnsSomeViewModel() { var viewModel = new EditorViewModel(); viewModel.SetIdentifier("XXX"); Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>()); } 

But that does not work. Because the asynchronous code was not executed before approval.

0
source share
2 answers

Your SetIdentifier method SetIdentifier also async (or you need to make it async because you will wait inside it. Then your method might look like this:

 public async Task SetIdentifier(string identifier) { await SetContentAsync(); DoSomething(); } 

And now you can just wait for it in unit test:

 [Test] public async Task Content_WhenModifierIsXXX_ReturnsSomeViewModel() { var viewModel = new EditorViewModel(); await viewModel.SetIdentifier("XXX"); Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>()); } 

You can also use the workaround to invoke your test synchronously:

 [Test] public async Task Content_WhenModifierIsXXX_ReturnsSomeViewModel() { Task.Run(async () => { var viewModel = new EditorViewModel(); await viewModel.SetIdentifier("XXX"); Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>()); }).GetAwaiter().GetResult(); } 

Via MSDN Magazine .

+1
source

When working with async you should always return a task. Otherwise, it will be β€œfire and forget”, and you absolutely cannot interact with Task .

Therefore, you must change the signature of SetIdentifier to return Task , for example:

 public async Task SetIdentifier(string identifier) { await SetContentAsync(); DoSomething(); } 

Then you can wait for the operation to complete in the test:

 [Test] public async void Content_WhenModifierIsXXX_ReturnsSomeViewModel() { var viewModel = new EditorViewModel(); await viewModel.SetIdentifier("XXX"); Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>()); } 

Or, if your test runner does not support async :

 [Test] public void Content_WhenModifierIsXXX_ReturnsSomeViewModel() { var viewModel = new EditorViewModel(); viewModel.SetIdentifier("XXX").Wait(); Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>()); } 
0
source

All Articles