LoginSignup
5
5

More than 5 years have passed since last update.

OHHTTPStubs関連のメモ

Last updated at Posted at 2015-02-14

iOSのアプリケーション開発で、ネットワーク関連の処理をユニットテストする際にはOHHTTPStubsを使うことが多いと思います。

この記事では、試したことやハマったことを備忘録的に書いていきます。

注意点

バックグラウンドで動作する機能のUTには使えない

バックグラウンドで動作する通信は、以下の理由でスタブすることができません。
* カスタマイズされたNSURLProtocolを使うことができない
* バックグラウンド転送はiOSがハンドリングしている

アップロードには対応していない

NSURLProtocolClientは、データが送信されたということを検知する手段がないため、アップロード関連の処理をスタブすることができません。

そのため、NSURLRequesthttpBody-[NSURLSession uploadTaskWithRequest:fromData:]などのデータを送っても、何も起こりません。
また、-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:も呼び出されません。

NSURLSessionと組み合わせる時の注意点

こちらの記事に書かれている通り、NSURLSessionを使ってPOSTのリクエストを送るときに、NSURLRequesthttpBodyにアクセスすることができません。
この現象はAppleのバグによるものです……。

そのため、以下のようにhttpBodyに埋め込まれたパラメータを元にスタブしたレスポンスの内容を変えたい、という処理が書きづらくなっています。

[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
    return [request.URL.host isEqualToString:@"127.0.0.1"];
} withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) {
    NSData *data = request.httpBody;
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    NSDictionary *responseHeader = @{@"Content-Type":@"application/json"};
    if (dict[@"key"] == @"hoge") {
        return [OHHTTPStubsResponse responseWithData:succeedResponseData statusCode:200 headers:responseHeader];
    } else {
        return [OHHTTPStubsResponse responseWithData:failedResponseData statusCode:200 headers:responseHeader];
    }
}];

対策として、以下のような選択肢が挙げられると思います。

  • こちらの記事に書かれている、AFNetworkingを使う回避策を試してみる。
  • gamakoさん記事を参考に、NSURLSessionNSURLSessionTaskをモックしてみる。
  • 厳しい現実を見つめなおす。回避策は諦め、テスト対象コードをもう少しテストしやすい設計になるよう見なおしてみる。(個別のリクエスト送信ごとにテストできる設計にするとか)

(この現象は、iOS8.1で確認した現象です。これ以降のiOSでは改善されているかもしれませんが……手元で確認してみましょう。)

[OHHTTPStubs removeAllStubs]はレスポンスの処理が終わってから実行しましょう

[OHHTTPStubs removeAllStubs]は、必ずOHHTTPStubsのレスポンスの処理が完了してから呼び出しましょう。
非同期なテストケースでレスポンスが完了していない場合に[OHHTTPStubs removeAllStubs]を実行すると、
正常にスタブを解除できないため、別なテストケースで使うときに失敗してしまう場合もあります。

なので、この記事にも書かれている通り、レスポンスの処理が終わってからテストを終了する、という形に書きましょう。
さもないと、「tearDownで正常に解除しているのに!」という羽目に陥りかねません。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5