web-dev-qa-db-ja.com

タスク<>結果をモックする方法は?

いくつかの単体テストをセットアップし、Rhino Mocksを使用して、テスト対象のオブジェクトを設定しています。 m笑されているものの1つはTask<HttpResponseMessage>。テスト対象のロジックには、非同期応答を取得するHttpClientへの呼び出しが含まれているためです。

だから私はこのようなモックのセットアップを始めました:

var httpClient = MockRepository.GenerateMock<HttpClient>();
var taskFunc = MockRepository.GenerateMock<Func<HttpResponseMessage>>();
var responseTask = MockRepository.GenerateMock<Task<HttpResponseMessage>>(taskFunc);
var response = MockRepository.GenerateMock<HttpResponseMessage>();

httpClient.Stub(c => c.PostAsJsonAsync<IEnumerable<LogMessage>>(Arg<string>.Is.Anything, Arg<IEnumerable<LogMessage>>.Is.Anything)).Return(responseTask);
responseTask.Stub(t => t.Result).Return(response);
response.Stub(r => r.IsSuccessStatusCode).Return(true);

(テストの「アクト」ステップは、テスト対象のオブジェクトをインスタンス化し、httpClientにフィードし、そのメソッドを実行することです。「アサート」は、モックを介して予期されるメソッド呼び出しが行われたことを確認しますそれらの上に。)

デバッガーでこれをステップ実行すると、この行に無期限のハングがあります。

responseTask.Stub(t => t.Result).Return(response);

Rhino MocksやC#非同期の経験はあまりないので、明らかなことを見落としているかもしれません。もちろん、目標は、.Resultプロパティはresponseモックを返します。しかし、私の試み自体がおそらく.Resultそれはたぶん単なるモックだから無期限に待つと思うだろうか?

これを整理する正しい方法は何ですか?基本的に、オブジェクトに模擬HttpClientを提供し、特定の引数を使用してメソッドが呼び出されたことをアサートする必要があります。

38
David

最も単純なことは、期待される結果で完了したタスクを返すことです。

var responseTask = Task.FromResult(response);

これがハングする理由は、モックされたタスクが開始されないために、指定されたfuncが実行されないためだと思います。テストで開始できます:

var responseTask = MockRepository.GenerateMock<Task<HttpResponseMessage>>(taskFunc);
responseTask.Start();

ただし、完了/失敗/キャンセルされたタスクを直接簡単に作成できるため、タスクをモックする理由はありません。

59
Lee