単体テストコードを書くことを考えると、外部のAPIにアクセスするような処理をMockに出来ないかなーとは思ってました。
私の場合はインターフェースを切ってました。
下記のライブラリを見つけました。
HttpClientクラスの代わりに処理するMockHttpClientクラスを提供します。
.NET Framework4.5にも対応しており、少し前のランタイムでも利用出来るので幅広く使えると思います。
実践
試しにGitHub APIのMockHttpClientを実装してみます。
GET https://api.github.com/repos/rimever/NLP100Knocks/languages
とした時、以下のようなレスポンスが
{ "C#": 267389, "HTML": 19081, "CSS": 1274, "JavaScript": 66 }
返却されるケースです。
/// <summary> /// https://developer.github.com/v3/ のMockHttpClientをつくって試します。 /// </summary> [Test] public async Task TryMockHttpClient() { var mockHttp = new MockHttpMessageHandler(); // example:https://api.github.com/repos/rimever/NLP100Knocks/languages mockHttp.When("https://api.github.com/repos/*/*/languages") // user名とリポジトリ名はパターンマッチ .Respond("application/json" , $@"{{ 'C#': 267389, 'HTML': 19081, 'CSS': 1274, 'JavaScript': 66, 'なぞのげんご': 9999 }}"); // Mockなので結果を一部ありえない結果にしてみる var client = mockHttp.ToHttpClient(); var response = await client.GetAsync("https://api.github.com/repos/user_name/repository_name/languages"); // ユーザー名と言語は任意の値でOK var json = await response.Content.ReadAsStringAsync(); Console.Write(json); }
問題なく意図した出力されました。
複数のWebAPIの振る舞いをさせる
一つのMockHttpClientに複数のWebAPIの処理を実装することも可能です。
これがナイスな点だと思います。先述した私のオレオレ設計だとWebAPI一つにつき1メソッドになりますので。
var mockHttp = new MockHttpMessageHandler(); // example:https://api.github.com/repos/rimever/NLP100Knocks/languages mockHttp.When("https://api.github.com/repos/*/*/languages") .Respond("application/json" , $@"{{ 'なぞのげんご': 9999 }}"); mockHttp.When("https://api.github.com/licenses").Respond("application/json" , $@"{{ {{ 'key': 'mit', 'name': 'MIT License', 'spdx_id': 'MIT', 'url': 'https://api.github.com/licenses/mit', 'node_id': 'MDc6TGljZW5zZW1pdA==' }} }}"); var client = mockHttp.ToHttpClient(); Console.WriteLine("リポジトリの言語取得サービスのモックを試します。"); { var response = await client.GetAsync("https://api.github.com/repos/user_name/repository_name/languages"); var json = await response.Content.ReadAsStringAsync(); Console.WriteLine(json); } Console.WriteLine("ライセンス一覧取得サービスのモックを試します。"); { var response = await client.GetAsync("https://api.github.com/licenses"); var json = await response.Content.ReadAsStringAsync(); Console.WriteLine(json); }