プロジェクトで新しいWeb APIビットを使用していますが、リクエストにクライアント証明書を追加する必要があるため、通常のHttpMessageRequest
を使用できないことがわかりました。その結果、私はHttpClient
を使用しています(そのため、WebRequestHandler
を使用できます)。これは、少なくともRhino Mocksにとってスタブ/モックフレンドリーではないことを除いて、すべてうまく機能します。
通常、代わりに使用するHttpClient
の周りにラッパーサービスを作成しますが、ラップする必要のあるメソッドが多数あるため、可能であればこれを避けたいと思います。私は何かが欠けていることを望んでいます—HttpClient
をスタブする方法について何か提案はありますか?
私はMoqを使用しており、HttpClientをスタブ化できます。これはRhino Mockでも同じだと思います(私は自分で試したことはありません)。 HttpClientをスタブしたい場合は、以下のコードが機能するはずです。
var stubHttpClient = new Mock<HttpClient>();
ValuesController controller = new ValuesController(stubHttpClient.Object);
私が間違っていたら訂正してください。ここで言及しているのは、HttpClient内のメンバーをスタブ化することだと思います。
最も一般的な分離/モックオブジェクトフレームワークでは、非仮想メンバーでスタブ/セットアップを実行できません。たとえば、次のコードは例外をスローします
stubHttpClient.Setup(x => x.BaseAddress).Returns(new Uri("some_uri");
また、多くのHttpClientメンバーをラップするため、ラッパーの作成を避けたいとも述べました。多くのメソッドをラップする必要がある理由は明らかではありませんが、必要なメソッドのみを簡単にラップできます。
例えば :
public interface IHttpClientWrapper { Uri BaseAddress { get; } }
public class HttpClientWrapper : IHttpClientWrapper
{
readonly HttpClient client;
public HttpClientWrapper() {
client = new HttpClient();
}
public Uri BaseAddress {
get
{
return client.BaseAddress;
}
}
}
他にも役立つと思われるオプション(たくさんの例があるので、コードは記述しません)Microsoft Moles Framework http://research.Microsoft.com/en-us/projects/moles/ Microsoft Fakes:(VS2012 Ultimateを使用している場合) http://msdn.Microsoft.com/en-us/library/hh549175.aspx
@Rajによってすでに提示されている優れたアイデアの代わりに、一歩下がってHttpMessageHandler
をモック/偽造することが可能かもしれません。
HttpClient
を必要とするクラスを、コンストラクターの依存関係注入パラメーターとして受け入れるようにすると、単体テスト時に、独自のHttpClient
で注入されたHttpMessageHandler
を渡すことができます。この単純なクラスには、次のように実装する必要がある抽象メソッドが1つだけあります。
public class FakeHttpMessageHandler : HttpMessageHandler
{
public HttpRequestMessage RequestMessage { get; private set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
RequestMessage = request;
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
}
}
私の簡単な例では、後で検査するためにHttpRequestMessage
をパブリックプロパティに保存し、HTTP 200(OK)を返しますが、必要な結果を設定するコンストラクターを追加することでこれを強化できます。
このクラスは次のように使用します。
public void foo()
{
//Arrange
var fakeHandler = new FakeHttpMessageHandler();
var client = new HttpClient(fakeHandler);
var SUT = new ClassUnderTest(client);
//Act
SUT.DomSomething();
//Assert
fakeHandler.RequestMessage.Method.ShouldEqual(HttpMethod.Get); // etc...
}
この方法には制限があります。たとえば、複数のリクエストを作成するメソッドや、複数のHttpClient
sを作成する必要があるメソッドでは、偽のハンドラーが複雑になりすぎる可能性があります。ただし、単純なケースでは検討する価値があります。
数か月前に MockHttp というライブラリをリリースしました。流暢な(拡張可能な)APIを備えたカスタムHttpMessageHandler
を使用します。モックされたハンドラー(またはHttpClient)をサービスクラスに挿入すると、構成されたとおりに応答します。
以下に基本的な使い方を示します。 When
メソッドとRespond
メソッドには、カスタムロジックの実行など、多数のオーバーロードがあります。 GitHubページのドキュメント では、さらに詳細に説明しています。
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localhost/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 = async client.GetAsync("http://localhost/api/user/1234");
// or without async: var response = client.GetAsync(...).Result;
var json = await response.Content.ReadAsStringAsync();
// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}