jeudi 28 décembre 2017

Running async tests for View Model in Xamarin and executing commands

This is a bit tricky to explain but hopefully my question will make sense. I have a long run of asyn methods that I want to test from my nUnit test project. There are twi scenarions the first one runs smooth and the second one fails but I want to fix the second one because it is correct.

Scenario N1 - tests green

[Test]
public async  Task NameNameName()
{
    var pageService = new Mock<IPageService>();
    var mvm = new MainViewModel(pageService.Object);
    await mvm.NewSurvey();

   Assert... bla bla all good
}

This test addresses a method called NewSurvey() in the MainViewModel class of my project which looks like this.

    public async Task NewSurvey()
    {

        var surveyController = ServiceLocator.Current.GetInstance<SurveyController>();
        var response = await surveyController.PostSurvey(CreateNewSurveyResourceObject());
        SetSurveyContext(response);
    }

As you might imagine when we hit PostSurvey we go along a continuous way of async await methods and when we get to the last one magic happens we come back to continue inside the method where we started from ie. execute SetSurveyContext(response);

Now, I made this method public just to see if it passes the test. I want to set it private since in the real app scenario the method is called through ICommand interface which is set up as follows in the constructor.

 NewSurveyCommand = new Command(async () => await NewSurvey());

With an appropriate public field

 public ICommand NewSurveyCommand { get; private set; }

Which is referenced from Xamarin xaml. The logic works fine in the app but I also want to write the test for it so here is how I do it.

[Test]
public async  Task NameNameName()
{
    var pageService = new Mock<IPageService>();
    var mvm = new MainViewModel(pageService.Object);

    //this time
    await Task.Run(() => mvm.NewSurveyCommand.Execute(null));
    //or below doesn't matter works the same way
    //mvm.NewSurveyCommand.Execute(null);

   Assert... bla bla all BAD this time
}

So the problem is when we get to the end of the chain of await async methods we get thrown back into the test method instead of finishing up the method inside MainViewModel where SetSurveyContext(response); actually sets what we are supposed to check for in the tests and the tests fail.

I have no idea how to fix this. Hopefully I have explained the issue well enough to someone to understand and possibly help me if they have been across the same problem. Thanks.

Aucun commentaire:

Enregistrer un commentaire