Just as an aside ... I gave up writing async unit tests years ago. After jumping through hoops I realised that testing the code synchronously proves that it works, then adding async testing just tests that the .NET asynchronous infrastructure works (which I expect is does!). Maybe the test harnesses are better at async testing now, but I generally avoid it except for rare critical or fragile async points -- *Greg K*
On 23 July 2015 at 17:28, Cormac Long <[email protected]> wrote: > Hi Tony, > > Change the return type of your test method to Task rather than void. > > Cheers, > Cormac > > On Thu, Jul 23, 2015 at 2:42 PM, Tony Wright <[email protected]> wrote: > >> Hi all, >> >> I have been trying to unit test an async call in an MVC app and I can't >> quite get it right. >> >> The application is an MVC app written in dot net. >> >> I am using xUnit to test the method, and Fluent Assertions to more >> naturally describe the expected outcome (BDD). >> >> The test case is a Quiz application. >> >> Here is the test: >> >> [Fact(DisplayName = "Calling the NextQuizQuestion api returns a question")] >> public async void CallingNextQuizQuestionGetsAResult() >> { >> //Arrange >> string userId = "[email protected]"; >> var triviaRepository = Mock.Create<TriviaRepository>(); >> Mock.Arrange(() => triviaRepository.NextQuestionAsync(userId)) >> .Returns(() => >> Task.FromResult( >> new TriviaQuestion >> { >> Title = "When was .NET first released?", >> Options = (new TriviaOption[] >> { >> new TriviaOption {Title = "2000", IsCorrect = >> false}, >> new TriviaOption {Title = "2001", IsCorrect = >> false}, >> new TriviaOption {Title = "2002", IsCorrect = true}, >> new TriviaOption {Title = "2003", IsCorrect = false} >> }).ToList() >> }) >> ).MustBeCalled(); >> >> //Act >> UnitOfWork uow = new UnitOfWork(triviaRepository); >> TriviaController controller = new TriviaController(uow); >> >> var taskResult = await controller.Get(); >> >> var result = Task.FromResult(taskResult); >> >> //Assert >> Assert.IsType<OkResult>(result.Result); >> >> } >> >> The controller method that I am instantiating is: >> >> [ResponseType(typeof(TriviaQuestion))]public async Task<IHttpActionResult> >> Get() >> { >> var userId = User.Identity.Name; >> >> TriviaQuestion nextQuestion = await >> unitOfWork.TriviaRepository.NextQuestionAsync(userId); >> >> if (nextQuestion == null) >> { >> return this.NotFound(); >> } >> >> return this.Ok(nextQuestion); >> } >> >> >> The test crashes on the line >> >> var taskResult = await controller.Get(); >> >> due to a timeout. >> >> The issue here I believe is that the test is single threaded and it never >> returns from the call because it doesn't have a synchronisation context to >> return to. >> >> Does anyone know how I can get this test to work? >> >> Regards, >> Tony >> > >
