web-dev-qa-db-ja.com

タスクを返すようにMoqに指示するにはどうすればよいですか?

宣言するインターフェースがあります

Task DoSomethingAsync();

私は自分のテストにMoqFrameworkを使っています。

[TestMethod()]
public async Task MyAsyncTest()
{
   Mock<ISomeInterface> mock = new Mock<ISomeInterface>();
   mock.Setup(arg => arg.DoSomethingAsync()).Callback(() => { <my code here> });
   ...
}

それから私のテストで私はawait DoSomethingAsync()を呼び出すコードを実行します。そしてテストはその行で失敗します。何がおかしいのですか?

248
Waldemar

あなたのメソッドはコールバックを持っていないので、.CallBack()を使う理由はありません。 .Returns()Task.FromResult を使用して、単純にTaskを希望の値で返すことができます。

MyType someValue=...;
mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.FromResult(someValue));

更新2014-06-22

Moq 4.2には、これを支援するための2つの新しい拡張方法があります。

mock.Setup(arg=>arg.DoSomethingAsync())
    .ReturnsAsync(someValue);

mock.Setup(arg=>arg.DoSomethingAsync())        
    .ThrowsAsync(new InvalidOperationException());

更新2016-05-05

Seth Flowersが その他の答え で述べているように、ReturnsAsyncTask<T>を返すメソッドに対してのみ利用可能です。 Taskだけを返すメソッドの場合、

.Returns(Task.FromResult(default(object)))

に使える。

この答え に示すように、.NET 4.6では、これは.Returns(Task.CompletedTask);に簡略化されています。

mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.CompletedTask);
555

類似の問題

私は大体次のようなインタフェースを持っています。

Task DoSomething(int arg);

症状

テスト対象のサービスawaitedDoSomethingへの呼び出しを行ったときに私のユニットテストが失敗しました。

このシナリオでは、このメソッドの.ReturnsAsync()Setup()を呼び出すことはできません。これは、このメソッドがTask<T>ではなく非総称のTaskを返すためです。

しかし、あなたはまだセットアップに.Returns(Task.FromResult(default(object)))を使うことができ、テストに合格することができます。

37
Seth Flowers

コールバックの後に.Returns(Task.FromResult(0));を追加するだけです。

例:

mock.Setup(arg => arg.DoSomethingAsync())
    .Callback(() => { <my code here> })
    .Returns(Task.FromResult(0));
22
Diego Torres

今、あなたはまたTalentsoft.Moq.SetupAsyncパッケージを使うことができます https://github.com/TalentSoft/Moq.SetupAsync

ここで見つかった回答とMoqに提案したアイデアはまだここにはまだ実装されていません。 https://github.com/moq/moq4/issues/384 、非同期メソッドの設定を大幅に簡素化します。

SetupAsync拡張機能を使用した以前の応答で見つかった例はほとんどありません。

mock.SetupAsync(arg=>arg.DoSomethingAsync());
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Callback(() => { <my code here> });
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Throws(new InvalidOperationException());
3
user9812476