非同期メソッドが正しいパラメーターで呼び出されたことを確認しようとしています。ただし、次の警告が表示されます。
「この呼び出しは待機されないため、現在のメソッドの実行は、呼び出しが完了する前に続行されます。呼び出しの結果に「待機」演算子を適用することを検討してください。」この警告は、_//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では、expectを呼び出して、テスト中のユニットが実行される前に呼び出すことができます。 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();
}
_
しかし、私はこれについてもっと良い解決策があるはずだと思いましたか?
バージョン1.9.0以降に更新するとすぐに、await
を受け取らずにNullReferenceException
を使用できるようになります。
Received()
述語が複雑すぎる場合やNSubstituteと一致しない場合は、常に callbacks を使用して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...
Jake Ginnivanの回答 は、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