1

I am trying to unit test an async methods of a search query. The unit test is defined below:

[Test]
public async Task MyTest1()
{
    var readyToScheduleQuery = new ReadyToScheduleQuery()
    {
        Facets = new List<Facet>() 
                 {  
                     new Facet() 
                     {
                         Name = "Service Type", 
                         Values = new List<FacetValue>()
                                  {  
                                      new FacetValue() 
                                      {  
                                          Value = "SomeJob", 
                                          Selected = true
                                      } 
                                  } 
                     } 
                 }
    };

    var result = readyToScheduleQuery.ExecuteAsync(_appointmentRespositoryStub); 

    Assert.IsNotNull(result); 
}

The ExecuteAsync method of readyToScheduleQuery is defined below:

internal async Task<ReadyToScheduleResult> ExecuteAsync(IAppointmentRepository appointments)
{
    var query = await appointments.GetReadyToSchedule(this.Id, exclude: NotificationTags.Something);

The unit test just hangs up and never returns a result. Any ideas?

It hangs up if I do the following: (Note the Result property at the end)

var result = readyToScheduleQuery.ExecuteAsync(_appointmentRespositoryStub).Result; 
Peter Szekeli
  • 2,712
  • 3
  • 30
  • 44
john doe
  • 9,220
  • 23
  • 91
  • 167
  • 3
    The first problem I see is that 'result' isn't a ReadyToScheduleResult object - it is a Task which means your IsNotNull assertion will pass. You need to await it. Are you sure that GetReadyToSchedule returns? – n8wrl Apr 11 '16 at 20:01
  • Yes, When I try to access .Result which contains the actual object. The unit test hangs and does not return. – john doe Apr 11 '16 at 20:03
  • I think GetReadyToSchedule is hanging up. Test this by taking it out of the test - try var query = await Task.FromResult(null) – n8wrl Apr 11 '16 at 20:05
  • It seems like it is hanging on the mocked respository. – john doe Apr 11 '16 at 20:10
  • 2
    Before you fix your repository, do two things: First sort out the awaits in THIS test. Then write tests for your mock repository to verify your fixes – n8wrl Apr 11 '16 at 20:11
  • @johndoe: Update NUnit if you haven't done so recently, and note the compiler warning on your unit test method. – Stephen Cleary Apr 12 '16 at 09:21

1 Answers1

3

You are missing an await. When writing your async/await you continue to call await on everything that is marked as async all the way down your callstack.

[Test]
public async Task MyTest1()
{
    var readyToScheduleQuery = new ReadyToScheduleQuery()
    {
        Facets = new List<Facet>() {  new Facet() {  Name = "Service Type", Values = new List<FacetValue>() {  new FacetValue() {  Value = "SomeJob", Selected = true} } } }                 
    };

    // missing await
    var result = await readyToScheduleQuery.ExecuteAsync(_appointmentRespositoryStub); 

    Assert.IsNotNull(result); // you will receive your actual expected unwrapped result here. test it directly, not the task.
}

This will hang.

var result = readyToScheduleQuery.ExecuteAsync(_appointmentRespositoryStub).Result; 

See this previous answer from Stephen Cleary as to why that is. Here again that answer (refer to the link though in case it has changed since the writing of this answer).

You're running into the standard deadlock situation that I describe on my blog and in an MSDN article: the async method is attempting to schedule its continuation onto a thread that is being blocked by the call to Result.

In this case, your SynchronizationContext is the one used by NUnit to execute async void test methods. I would try using async Task test methods instead.

Community
  • 1
  • 1
Igor
  • 60,821
  • 10
  • 100
  • 175