web-dev-qa-db-ja.com

.NETテストでモックされたHttpClientを渡す方法は?

Microsoft.Net.Httpを使用していくつかのJsonデータを取得するサービスがあります。すばらしいです!

もちろん、ユニットテストが実際のサーバーにヒットするのは望ましくありません(そうでなければ、それは統合テストです)。

これが私のサービスアクターです(依存性注入を使用しています...)

public Foo(string name, HttpClient httpClient = null)
{
...
}

..... MoqまたはFakeItEasyと言うと、どうやってこれをモックできるのかわかりません。

私のサービスがGetAsyncまたはPostAsync ..を呼び出すとき、それらの呼び出しを偽造できることを確認したいと思います。

私はそれをどのように行うことができますか?

私は-望んでいます-私は自分のラッパーを作成する必要はありません..それはがらくたの原因です:(Microsoftはこれで見落としができませんでした?

(はい、ラッパーを作るのは簡単です..私は以前にそれらをやったことがあります...しかしそれはポイントです!)

55
Pure.Krome

コアのHttpMessageHandlerを偽のものに置き換えることができます。このように見えるもの...

public class FakeResponseHandler : DelegatingHandler
    {
        private readonly Dictionary<Uri, HttpResponseMessage> _FakeResponses = new Dictionary<Uri, HttpResponseMessage>(); 

        public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
        {
                _FakeResponses.Add(uri,responseMessage);
        }

        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            if (_FakeResponses.ContainsKey(request.RequestUri))
            {
                return _FakeResponses[request.RequestUri];
            }
            else
            {
                return new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request};
            }

        }
    }

そして、偽のハンドラーを使用するクライアントを作成できます。

var fakeResponseHandler = new FakeResponseHandler();
fakeResponseHandler.AddFakeResponse(new Uri("http://example.org/test"), new HttpResponseMessage(HttpStatusCode.OK));

var httpClient = new HttpClient(fakeResponseHandler);

var response1 = await httpClient.GetAsync("http://example.org/notthere");
var response2 = await httpClient.GetAsync("http://example.org/test");

Assert.Equal(response1.StatusCode,HttpStatusCode.NotFound);
Assert.Equal(response2.StatusCode, HttpStatusCode.OK);
95
Darrel Miller

これは古い質問であることは知っていますが、このトピックの検索中に偶然見つけて、HttpClientのテストを簡単にする非常に良いソリューションを見つけました。

Nugetから入手できます。

https://github.com/richardszalay/mockhttp

PM> Install-Package RichardSzalay.MockHttp

使用方法を簡単に説明します。

var mockHttp = new MockHttpMessageHandler();

// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localost/api/user/*")
        .Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON

// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);

var response = await client.GetAsync("http://localost/api/user/1234");
// or without await: var response = client.GetAsync("http://localost/api/user/1234").Result;

var json = await response.Content.ReadAsStringAsync();

// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}

Githubプロジェクトページの詳細。これが役に立つことを願っています。

18
Fedaykin

警告を回避するためにTask.FromResultを使用している @ Darrel Miller の答えを少し変更するだけですawait演算子を期待する非同期メソッドについて。

public class FakeResponseHandler : DelegatingHandler
{
    private readonly Dictionary<Uri, HttpResponseMessage> _FakeResponses = new Dictionary<Uri, HttpResponseMessage>();

    public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
    {
        _FakeResponses.Add(uri, responseMessage);
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        if (_FakeResponses.ContainsKey(request.RequestUri))
        {
            return Task.FromResult(_FakeResponses[request.RequestUri]);
        }
        else
        {
            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request });
        }
    }
}
2
Rui Taborda

Microsoft Fakes 、特にShims-セクションをご覧ください。それらを使用すると、HttpClient自体の動作を変更できます。前提条件は、VS PremiumまたはUltimateを使用していることです。

1
ElGauchooo