0
3

More than 1 year has passed since last update.

iOSアプリの通信エラーをブレークポイントで起こす

Posted at

はじめに

一般的にiOSアプリで通信エラーを起こすには

  • 機内モードをオンにする
  • WiFiをオフにする
  • Network Link Conditionerをオンにする
  • 有線LANを抜く

などの方法がありますが、再接続に時間がかかったり、確認中はチャットやメールが使えないといった問題が起きます。
そこでXcodeのブレークポイントを用いた手法をおすすめします。

実例

APIリクエストを行う共通関数があるとします。

// 通信エラー時は completion の引数に nil が渡される
func requestApi(url: URL, completion: @escaping (Dictionary<String, Any>?) -> Void) {
    let request = URLRequest(url: url)
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        let json = try? JSONSerialization.jsonObject(with: data!, options: [])
        completion(json as? Dictionary<String, Any>)
    }
    task.resume()
}

その関数にブレークポイントを設定します。
breakpoint.png
これでブレークポイントがオンの場合に通信エラーが起きます。

解説

ブレークポイントのDebugger CommandでLLDBコマンドを2つ使っています。

  • po completion()
    • 通信エラーを疑似的に起こすための処理
    • 今回の関数は通信エラー時にnilを渡す仕様なので、completion()としている
  • thread return
    • 正規のレスポンスを使用させないための処理
    • swiftのreturnと同様に、関数内の残りの処理を実行せずに呼び出し元に戻る

Automatically continue after evaluating actionsをオンにすることで、ブレークポイントで停止しないようにしています。
po completion()の箇所は実際の関数に合わせた実装が必要ですが、1度作れば使いまわせるため手間がかかるのは最初だけです。

この手法は以下メリットがあります。

  • ブレークポイントなので、ワンクリックでオン・オフの切り替えが可能
  • Mac・スマホの他の通信は遮断しないため、メールやチャットが使用できる
  • 特定のAPIでのみ通信エラーを起こすことが可能(後述)

注意事項

この手法は開発中に使う時短テクニックです。
ブレークポイントを設定した通信処理のみエラーになるため、WebViewやFirebaseなどが行う通信はエラーになりません。
そのためテストではこの手法を使うべきではありません。

応用編

ブレークポイントを調整することで、特定APIでのみ通信エラーを起こしたり、通信エラー以外にも使えます。

応用編1.特定のAPIでのみ通信エラーを起こす

ブレークポイントのConditionに条件を設定することで、特定のAPIやパラメータの時のみ通信エラーを起こすことができます。
condition.png
Conditionに設定した条件response?.url?.path == "/api/v2/items"trueの場合に、Debugger Commandが実行されて通信エラーになります。
この手法は特に以下ケースで有効です。

  • ページネーションされたAPIの1ページ目のリクエストは成功させて、2ページ目のリクエストを失敗させる
  • 同時にリクエストする2つのAPIのうち、片方だけ失敗させる

応用編2.レスポンスの改ざん

ブレークポイントでレスポンスを改ざんできます。
limit.png
po result = ["type": "limit", "message": "limit"]によりAPIレスポンス(result)を上書きしています。
この手法は特に以下ケースで有効です。

  • APIのリクエスト回数超過エラーといった、起こすのに手間がかかるエラーケースの動作確認
  • APIが未完成の状況下でアプリの動作確認
  • APIサーバがメンテナンス中である場合を想定した動作確認

大きなレスポンスの改ざんはLLDBではやりづらいため、その場合は素直にCharlesなどを使いましょう。

応用編3:通信速度を遅くする

Network Link Conditionerを使って低速環境の再現をするケースが多いですが、ブレークポイントでもできます。
sleep.png
po Thread.sleep(forTimeInterval: 10)によりコールバックを遅延させています。
メインスレッドでsleep()を実行しないように、ブレークポイントの位置には注意が必要です。

この手法は特に以下ケースで有効です。

  • 通信中にインジゲータが表示されているか確認
  • 通信中にタップやサスペンドレジュームをしても問題が起きないか確認
0
3
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
0
3