单元测试使用NUnit和C#的异步方法

时间:2016-04-11 19:56:43

标签: c# unit-testing

我正在尝试对搜索查询的异步方法进行单元测试。单元测试定义如下:

[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); 
}

readyToScheduleQuery的ExecuteAsync方法定义如下:

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

单元测试只是挂断而且永远不会返回结果。有任何想法吗?

如果我执行以下操作,它会挂断:(注意最后的Result属性)

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

1 个答案:

答案 0 :(得分:3)

你错过了等待。在编写async / await时,你继续在你的callstack上一直调用等待标记为async的所有内容。

[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.
}

这会挂起。

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

请参阅Stephen Cleary的this previous answer,了解其原因。这里再次回答(引用链接,但如果自写这个回答以来它已经改变)。

  

您正在遇到我在我的博客和MSDN文章中描述的标准死锁情况:异步方法正在尝试将其继续安排到被Result调用阻止的线程上。

     

在这种情况下,您的SynchronizationContext是NUnit用于执行异步void测试方法的SynchronizationContext。我会尝试使用异步任务测试方法。