NSubstitute - 收到异步 - “等待呼叫”警告

时间:2015-07-09 13:14:19

标签: c# unit-testing asynchronous async-await nsubstitute

我正在尝试验证是否使用正确的参数调用了异步方法。但是,我收到了警告:

"由于未等待此调用,因此在完成调用之前,将继续执行当前方法。考虑应用“等待”#39;运营商对呼叫的结果"。此警告显示在//Assert评论(下方)下面的代码行中。

我使用 NSubstitute 的测试如下:

[Test]
public async Task SimpleTests()
{
  //Arrange
  var request = CreateUpdateItemRequest();

  databaseHelperSub.ExecuteProcAsync(Arg.Any<DatabaseParams>()).Returns(Task.FromResult((object)null));

  //Act      
  await underTest.ExecuteAsync(request);

  //Assert
  databaseHelperSub.Received().ExecuteProcAsync(Arg.Is<DatabaseParams>(
    p => p.StoredProcName == StoredProcedureName
         && p.Parameters[0].ParameterName == "Param1"
         && p.Parameters[0].Value.ToString() == "Value1"
         && p.Parameters[1].ParameterName == "Param2"
         && p.Parameters[1].Value.ToString() == "Value2"));
}

被测单位方法underTest.ExecuteAsync(request)调用ExecuteProcedureAsync并执行等待:

var ds = await DatabaseHelper.ExecuteProcAsync(dbParams);

由于使用NSubstitute,在执行被测单元后需要Received()。而在RhinoMocks中,您可以期望在执行测试单元之前进行调用。 RhinoMocks可以返回Task.FromResult(),而NSubstitute则不能。

有效的RhinoMocks是:

[Test]
        public async Task SimpleTest()
        {
            // Arrange
            var request = new UpdateItemRequest();

            databaseHelperMock.Expect(m => m.ExecuteProcAsync(Arg<DatabaseParams>.Matches(
                p =>   p.StoredProcName == StoredProcedureName
                    && p.Parameters[0].ParameterName == "Param1"
                    && p.Parameters[0].Value.ToString() == "Value1"
                    && p.Parameters[1].ParameterName == "Param2"
                    && p.Parameters[1].Value.ToString() == "Value2
                ))).Return(Task.FromResult<object>(null));

            // Act
            await underTest.ExecuteAsync(request);

        }

我已经看到有一种解决方法,您可以添加扩展方法来解决问题:

  public static class TestHelper
  {
    public static void IgnoreAwait(this Task task)
    {

    }
  }

意味着 NSubstitute 的测试行可以按如下方式执行,警告就会消失:

databaseHelperSub.Received().ExecuteProcAsync(Arg.Is<DatabaseParams>(
        p => p.StoredProcName == StoredProcedureName
             && p.Parameters[0].ParameterName == "Param1"
             && p.Parameters[0].Value.ToString() == "Value1"
             && p.Parameters[1].ParameterName == "Param2"
             && p.Parameters[1].Value.ToString() == "Value2")).IgnoreAwait();
    }

但是,我认为必须有一个更好的解决方案吗?

2 个答案:

答案 0 :(得分:20)

只要您更新到1.9.0或更高版本,就可以在不接收await的情况下使用NullReferenceException

答案 1 :(得分:2)

Jake Ginnivan answer解释了对于Received await不是必需的,但是编译器不理解它。

您可以安全地禁止警告

 #pragma warning disable 4014 //for .Received await is not required, so suppress warning “Consider applying the 'await' operator”
   _service.Received(totalNumber).MyMethod(Arg.Any<ParamType>());
 #pragma warning restore 4014