まず質問への回答の前に注意点を一つ。
HttpClientはIDisposableを実装しているのでちゃんとDisposeしましょう。
可能であればTak1waさんの言っているDIを実装した方がいいです。
DIっていうのは、以下みたいに書き換えることです。
CSharp
1public class TargetClass : IDisposable
2{
3 private readonly HttpClient httpClient;
4
5 // これがDI、依存性注入ということ
6 public TargetClass(HttpClient httpClient)
7 {
8 this.httpClient = httpClient;
9 }
10
11 public async Task<ResultType> ExecuteHttpRequestAsync()
12 {
13 try
14 {
15 var reqMessage = new HttpRequestMessage();
16
17 // 中略
18
19 // HTTPリクエスト送信
20 using (HttpResponseMessage response = await httpClient.SendAsync(reqMessage)
21 {
22 if (response.StatusCode == HttpStatusCode.OK)
23 {
24 // リクエスト成功
25 return ResultType.OK;
26 }
27 else
28 {
29 // リクエスト失敗
30 return ResultType.NG;
31 }
32 }
33 }
34 catch (TaskCanceledException)
35 {
36 // タイムアウト
37 return ResultType.Timeout;
38 }
39 }
40}
HttpClientはFakes使わなくてもHttpMessageHandlerを使って挙動が変更できます。
HttpMessageHandlerのメソッド内で常に例外を返すようにしてもいいですし、複雑なシナリオに対応する場合にはこういったモック用のハンドラを使うことができます。
後は、テストコードで期待する挙動のHttpMessageHandler継承クラスを渡してあげればいいです。
CSharp
1[TestCase(ResultType.OK)]
2[TestCase(ResultType.NG)]
3[TestCase(ResultType.Timeout)]
4public async Task ExecuteHttpRequestAsyncTest(ResultType result)
5{
6 using(var client = new HttpClient(new WillThrowHandler()))
7 {
8 var tagetClass = new TargetClass(client);
9 ResultType resultType = await targetClass.ExecuteHttpRequestAsync();
10
11 // 結果確認
12 Assert.AreEqual(result, resultType);
13 }
14}
ただ、上記のコード、HttpClientがIDisposableを継承するために呼び出しの処理が変わってしまいます。
それも嫌って動作を変えるとなると…HttpClientの挙動をファクトリを変更する感じで実装ですかね。
ただまあ…そのためだけにこんなメソッドがテスト以外でもコンストラクタにつくと気持ち悪いですけどね。。
CSharp
1public class TargetClass : IDisposable
2{
3 private static readonly Func<HttpClient> DefaultFactory = () => new HttpClient();
4 private readonly Func<HttpClient> httpClientFactory;
5
6 public TargetClass()
7 {
8 this.httpClientFactory = DefaultFactory;
9 }
10 public TargetClass(Func<HttpClient> httpClientFactory)
11 {
12 this.httpClientFactory = httpClientFactory;
13 }
14
15 public async Task<ResultType> ExecuteHttpRequestAsync()
16 {
17 try
18 {
19 using (var client = httpClientFactory())
20 {
21 var reqMessage = new HttpRequestMessage();
22
23 // 中略
24
25 // HTTPリクエスト送信
26 using (HttpResponseMessage response = await client.SendAsync(reqMessage)
27 {
28 if (response.StatusCode == HttpStatusCode.OK)
29 {
30 // リクエスト成功
31 return ResultType.OK;
32 }
33 else
34 {
35 // リクエスト失敗
36 return ResultType.NG;
37 }
38 }
39 }
40 }
41 catch (TaskCanceledException)
42 {
43 // タイムアウト
44 return ResultType.Timeout;
45 }
46 }
47}
この場合呼び出し方はこうなります。
CSharp
1[TestCase(ResultType.OK)]
2[TestCase(ResultType.NG)]
3[TestCase(ResultType.Timeout)]
4public async Task ExecuteHttpRequestAsyncTest(ResultType result)
5{
6 var tagetClass = new TargetClass(() => new HttpClient(new WillThrowHandler()));
7 ResultType resultType = await targetClass.ExecuteHttpRequestAsync();
8
9 // 結果確認
10 Assert.AreEqual(result, resultType);
11}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/12/27 11:57