Skip to content

Commit

Permalink
Added link to blog post
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkagamine committed Apr 13, 2019
1 parent 6971035 commit 8b04f3a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 28 deletions.
34 changes: 18 additions & 16 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

[![NuGet](https://img.shields.io/nuget/v/MaxKagamine.Moq.HttpClient.svg)](https://www.nuget.org/packages/MaxKagamine.Moq.HttpClient/) [![Travis](https://img.shields.io/travis/com/maxkagamine/Moq.HttpClient.svg)](https://travis-ci.com/maxkagamine/Moq.HttpClient)

[English](README.md)
[ブログ投稿](https://maxkagamine.jp/blog/moq-de-httpclient-to-ihttpclientfactory-o-mokkusuru-kantanna-houhou)  ·  [English](README.md)

MoqでHttpClientとIHttpClientFactoryのテストダブルを作るため拡張メソッドのセットです

HttpClientを直にモックすることが難しいのは[よく知られています](https://github.com/dotnet/corefx/issues/1624)。普通の仕方はモックできられる何らかのラッパーを作るかHttpClientのために特別にテスティングライブラリを使うことですけど、前者はよく望ましくなくて、後者はHTTPリクエストだけのために別のモックシステムに切り替えることが必要で、あのシステムの方が柔軟ではないか他のモックと一緒に不味そうですかもしれない。この拡張ではたくさんのボイラプレートなしで他のすべてと同じようにMoqでHttpClientをモックできます

- [インストール](#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
- [API](#api)
- [リクエスト](#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88)
- [レスポンス](#%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9)
- [リクエスト](#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88)
- [レスポンス](#%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9)
- [用例](#%E7%94%A8%E4%BE%8B)
- [一般的な使用法](#%E4%B8%80%E8%88%AC%E7%9A%84%E3%81%AA%E4%BD%BF%E7%94%A8%E6%B3%95)
- [ヘッダーとかJSONとかクエリパラメータでリクエストをマッチする](#%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%81%A8%E3%81%8Bjson%E3%81%A8%E3%81%8B%E3%82%AF%E3%82%A8%E3%83%AA%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%81%A7%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%82%92%E3%83%9E%E3%83%83%E3%83%81%E3%81%99%E3%82%8B)
- [リクエストのシークエンスをセットアップする](#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E3%82%B7%E3%83%BC%E3%82%AF%E3%82%A8%E3%83%B3%E3%82%B9%E3%82%92%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%81%99%E3%82%8B)
- [リクエストの本体に基づいてレスポンスを書く](#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E6%9C%AC%E4%BD%93%E3%81%AB%E5%9F%BA%E3%81%A5%E3%81%84%E3%81%A6%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%82%92%E6%9B%B8%E3%81%8F)
- [IHttpClientFactoryの使い方](#ihttpclientfactory%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9)
- [完全なユニットテストの用例](#%E5%AE%8C%E5%85%A8%E3%81%AA%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E7%94%A8%E4%BE%8B)
- [一般的な使用法](#%E4%B8%80%E8%88%AC%E7%9A%84%E3%81%AA%E4%BD%BF%E7%94%A8%E6%B3%95)
- [ヘッダーとかJSONとかクエリパラメータでリクエストをマッチする](#%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%81%A8%E3%81%8Bjson%E3%81%A8%E3%81%8B%E3%82%AF%E3%82%A8%E3%83%AA%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%81%A7%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%82%92%E3%83%9E%E3%83%83%E3%83%81%E3%81%99%E3%82%8B)
- [リクエストのシークエンスをセットアップする](#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E3%82%B7%E3%83%BC%E3%82%AF%E3%82%A8%E3%83%B3%E3%82%B9%E3%82%92%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%81%99%E3%82%8B)
- [リクエストの本体に基づいてレスポンスを書く](#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E6%9C%AC%E4%BD%93%E3%81%AB%E5%9F%BA%E3%81%A5%E3%81%84%E3%81%A6%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%82%92%E6%9B%B8%E3%81%8F)
- [IHttpClientFactoryの使い方](#ihttpclientfactory%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9)
- [完全なユニットテストの用例](#%E5%AE%8C%E5%85%A8%E3%81%AA%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E7%94%A8%E4%BE%8B)
- [ライセンス / 寄付](#%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9--%E5%AF%84%E4%BB%98)

## インストール
Expand All @@ -40,7 +40,7 @@ HttpClientを直にモックすることが難しいのは[よく知られてい

### リクエスト

すべとのSetupとVerifyのヘルパーはここで略した同じヘルパーがあります
すべとのSetupとVerifyのヘルパーはここで略した同じオーバーロードがあります

```csharp
SetupAnyRequest()
Expand All @@ -53,7 +53,7 @@ SetupRequest(HttpMethod method, string|Uri requestUrl[, Predicate<HttpRequestMes

### レスポンス

レスポンスのヘルパーはStringContent、ByteArrayContent、StreamContentかステータスコードだけを送ることを簡単になります。すべてのオーバーロードはレスポンスをもっとコンフィグする(つまり、ヘッダーを設定する)ためActionを受け取ります
レスポンスのヘルパーはStringContent、ByteArrayContent、StreamContentかステータスコードだけを送ることを簡単にします。すべてのオーバーロードはレスポンスをもっとコンフィグする(つまり、ヘッダーを設定する)ためActionを受け取ります

```csharp
ReturnsResponse(HttpStatusCode statusCode[, HttpContent content], Action<HttpResponseMessage> configure = null)
Expand Down Expand Up @@ -103,13 +103,13 @@ handler
{
// このセットアップは予期された (expected) IDがあるリクエストのみをマッチする
var json = await request.Content.ReadAsStringAsync();
var model = JsonConvert.DeserializeObject<Model>()
var model = JsonConvert.DeserializeObject<Model>();
return model.Id == expected.Id;
})
.ReturnsResponse(HttpStatusCode.Created);

// 他に関係なく特定のクエリパラメータをチェックするためも使えます
handler.SetupRequest(r => ((Url) r.RequestUri).QueryParams["foo"].Equals("bar"))
handler.SetupRequest(r => ((Url) r.RequestUri).QueryParams["hoge"].Equals("piyo"))
.ReturnsResponse("stuff");
```

Expand Down Expand Up @@ -144,9 +144,9 @@ var body = await response.Content.ReadAsStringAsync(); // こんにちは、世

### IHttpClientFactoryの使い方

HttpClientが`IDisposable`だから`using`の中でよく見られますが、これは[実は正しくないしアプリがソケットを平らげているのにつながります](https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/)普通の忠告はアプリケーションのライフタイムの全期間staticかsingletonなHttpClientを保つことですがこらはDNSの変更に反応しないというマイナスがあります
HttpClientが`IDisposable`だから`using`の中でよく見られますが、これは[実は正しくないしアプリがソケットを平らげているのにつながります](https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/)普通の忠告はアプリケーションのライフタイムの全期間staticかsingletonなHttpClientを保つことですがこれはDNSの変更に反応しないというマイナスがあります

ASP.NET Coreは「HttpClientのライフタイムを手動で管理するときに発生する一般的なDNSの問題を回避のために基礎となるHttpClientMessageHandlerインスタンスのプーリングとライフタイムを管理する」という新しい[IHttpClientFactory](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests)を導入します。ボーナスとして、これはHttpClientのよく知られていないフィーチャーをもっととっつきやすいにする:ミドルウェアをプラグインする能力(例えば、再試行と失敗を自動的に処理するために[Polly](https://github.com/App-vNext/Polly#polly)を使う)
ASP.NET Coreは「HttpClientのライフタイムを手動で管理するときに発生する一般的なDNSの問題を回避のために基礎となるHttpClientMessageHandlerインスタンスのプーリングとライフタイムを管理する」という新しい[IHttpClientFactory](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/http-requests)を導入します。ボーナスとして、これはHttpClientのあまり知られていないフィーチャーをもっととっつきやすいにする:ミドルウェアをプラグインする能力(例えば、再試行と失敗を自動的に処理するために[Polly](https://github.com/App-vNext/Polly#polly)を使う)

利用法次第では、コンストラクタが単にIHttpClientFactoryによって注入したHttpClientを受け取るかもしれない。コンストラクタはファクトリーそのものを受け取れば、これは同じようにモックされる:

Expand Down Expand Up @@ -180,7 +180,7 @@ MITライセンス

決して必要ではないけれど、もしこれが役立つならば、寄付がすごく感謝されます:

**[PayPal.me](https://paypal.me/maxkagamine)**
[![PayPal.me](https://www.paypalobjects.com/digitalassets/c/website/marketing/apac/C2/logos-buttons/optimize/34_Blue_PayPal_Pill_Button.png)](https://www.paypal.me/maxkagamine/0jpy?country.x=JP&locale.x=ja_JP)

<p>
<details>
Expand All @@ -191,6 +191,8 @@ MITライセンス
BTC 32SEpPUowijZWET5tbErgskNSBkjSmLwmo
BCH 1DsWr5aoyQgcD6vYCTSViVmUcRSiYPPvPw
DOGE DAEiyJP7F7YqZN9GJ12Z2RhfkPahyyN1DY
ありがとうございます!
```
</details>
</p>
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

[![NuGet](https://img.shields.io/nuget/v/MaxKagamine.Moq.HttpClient.svg)](https://www.nuget.org/packages/MaxKagamine.Moq.HttpClient/) [![Travis](https://img.shields.io/travis/com/maxkagamine/Moq.HttpClient.svg)](https://travis-ci.com/maxkagamine/Moq.HttpClient)

[日本語](README.ja.md)
[Blog post](https://maxkagamine.com/blog/mocking-httpclient-ihttpclientfactory-with-moq-the-easy-way) &nbsp;&middot;&nbsp; [日本語](README.ja.md)

A set of extension methods for mocking HttpClient and IHttpClientFactory with Moq.

Mocking HttpClient directly is [notoriously difficult](https://github.com/dotnet/corefx/issues/1624); the general approach has been to either create a wrapper of some form to mock instead or use a specific testing library. However, the former is typically undesirable, and the latter requires switching to a separate mocking system for HTTP calls which may be less flexible or awkward in conjunction with other mocks. These extensions instead allow HttpClient to be mocked the same way as everything else using Moq without excessive boilerplate.

- [Install](#install)
- [API](#api)
- [Request](#request)
- [Response](#response)
- [Request](#request)
- [Response](#response)
- [Examples](#examples)
- [General usage](#general-usage)
- [Matching requests by headers, JSON, query params, etc.](#matching-requests-by-headers-json-query-params-etc)
- [Setting up a sequence of requests](#setting-up-a-sequence-of-requests)
- [Composing responses based on the request body](#composing-responses-based-on-the-request-body)
- [Using IHttpClientFactory](#using-ihttpclientfactory)
- [Complete unit test examples](#complete-unit-test-examples)
- [General usage](#general-usage)
- [Matching requests by headers, JSON, query params, etc.](#matching-requests-by-headers-json-query-params-etc)
- [Setting up a sequence of requests](#setting-up-a-sequence-of-requests)
- [Composing responses based on the request body](#composing-responses-based-on-the-request-body)
- [Using IHttpClientFactory](#using-ihttpclientfactory)
- [Complete unit test examples](#complete-unit-test-examples)
- [License / Donate](#license--donate)

## Install
Expand Down Expand Up @@ -103,7 +103,7 @@ handler
{
// This setup will only match calls with the expected id
var json = await request.Content.ReadAsStringAsync();
var model = JsonConvert.DeserializeObject<Model>()
var model = JsonConvert.DeserializeObject<Model>();
return model.Id == expected.Id;
})
.ReturnsResponse(HttpStatusCode.Created);
Expand Down Expand Up @@ -178,9 +178,9 @@ Though it may be a faux pas to point to the unit tests as documentation, in this

MIT license.

Although by no means necessary, if you find this useful, donations are greatly appreciated:
If you found this useful, please consider buying me a ~~coffee~~ cup of tea!

**[PayPal.me](https://paypal.me/maxkagamine)**
[![PayPal.me](https://www.paypalobjects.com/digitalassets/c/website/marketing/apac/C2/logos-buttons/optimize/34_Blue_PayPal_Pill_Button.png)](https://paypal.me/maxkagamine)

<p>
<details>
Expand All @@ -191,6 +191,8 @@ Although by no means necessary, if you find this useful, donations are greatly a
BTC 32SEpPUowijZWET5tbErgskNSBkjSmLwmo
BCH 1DsWr5aoyQgcD6vYCTSViVmUcRSiYPPvPw
DOGE DAEiyJP7F7YqZN9GJ12Z2RhfkPahyyN1DY
Thank you! I wish you a safe journey to the moon :)
```
</details>
</p>

0 comments on commit 8b04f3a

Please sign in to comment.