C# NSubstitute-接收异步-“;未等待呼叫”;警告

C# NSubstitute-接收异步-“;未等待呼叫”;警告,c#,unit-testing,asynchronous,async-await,nsubstitute,C#,Unit Testing,Asynchronous,Async Await,Nsubstitute,我试图验证是否使用正确的参数调用了异步方法。然而,我得到了警告: ”由于此调用没有等待,当前方法的执行在调用完成之前继续。请考虑将“Acess”运算符应用到调用的结果中。此警告出现在//Assert注释(下面)下面的代码行上 我使用NSubstitute进行的测试如下: [Test] public async Task SimpleTests() { //Arrange var request = CreateUpdateItemRequest(); databaseHelperS

我试图验证是否使用正确的参数调用了异步方法。然而,我得到了警告:

”由于此调用没有等待,当前方法的执行在调用完成之前继续。请考虑将“Acess”运算符应用到调用的结果中。此警告出现在

//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"));
}
由于使用NSubstitute,在执行被测单元之后需要Received()。而在Rhinomock中,您可以期望在执行测试单元之前发生调用。Rhinomock可以返回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);

        }
这意味着我的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();
    }
databaseHelperSub.Received().ExecuteLocasync(Arg.Is(
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();
}

但是,我认为一定有更好的解决方案?

每当
Received()
谓词变得太复杂或与NSubstitute不匹配时,您可以始终使用
When().Do()
AndDoes()
捕获指定的参数。对于您的用例,应该是这样的

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

//Act      
await underTest.ExecuteAsync(request);

//Assert
receivedParms.Should().NotBeNull();
// assert your parms...
DatabaseParams receivedParms=null;
databaseHelperSub.ExecuteLocasync(Arg.Any())
.Returns(Task.FromResult((对象)null))
.AndDoes(x=>receivedParms=x.Arg);
//表演
等待测试不足。ExecuteAsync(请求);
//断言
receivedParms.Should().NotBeNull();
//坚持你的观点。。。

一旦更新到1.9.0版或更高版本,您就可以使用
wait
而不必接收
NullReferenceException
说明for Received wait不是必需的,但是编译器不理解它

您可以安全地抑制该警告

 #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
<代码> >语用障碍警告禁用4014 / /。接收等待不是必需的,因此禁止警告“考虑应用‘等待’操作符”。 _service.Received(totalNumber).MyMethod(Arg.Any()); #pragma警告恢复4014
这是一个编译器警告,说明您忘记在异步方法之前放置
wait
。如果在调用之前放置wait,为什么不在
//Assert
之后的行中放置
wait
。测试失败,因为它接收到空引用异常。NSubstitute目前没有更好的方法来处理此问题。请看Jake在这里的解释:可能值得NSub更改,我在这里提出了一个问题:可能与上下文无关,但我仍然想推荐
Moq
。。看起来你可以使用Moq.Verify()你知道1.8.3什么时候发布吗?我现在有这个问题,我不知道。不过你应该问问大卫·切帕克(也许是通过)。他是NSubstitute的维护者。@levelis正是你所知道的。NSubstitute的V1.9.0现已发布。其中包含的增强功能将解决此堆栈溢出问题。
DatabaseParams receivedParms = null;
databaseHelperSub.ExecuteProcAsync(Arg.Any<DatabaseParams>())
  .Returns(Task.FromResult((object)null))
  .AndDoes(x => receivedParms = x.Arg<DatabaseParams>);

//Act      
await underTest.ExecuteAsync(request);

//Assert
receivedParms.Should().NotBeNull();
// assert your parms...
 #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