はじめに
一般的に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()
}
その関数にブレークポイントを設定します。
これでブレークポイントがオンの場合に通信エラーが起きます。
解説
ブレークポイントの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に設定した条件response?.url?.path == "/api/v2/items"
がtrue
の場合に、Debugger Command
が実行されて通信エラーになります。
この手法は特に以下ケースで有効です。
- ページネーションされたAPIの1ページ目のリクエストは成功させて、2ページ目のリクエストを失敗させる
- 同時にリクエストする2つのAPIのうち、片方だけ失敗させる
応用編2.レスポンスの改ざん
ブレークポイントでレスポンスを改ざんできます。
po result = ["type": "limit", "message": "limit"]
によりAPIレスポンス(result
)を上書きしています。
この手法は特に以下ケースで有効です。
- APIのリクエスト回数超過エラーといった、起こすのに手間がかかるエラーケースの動作確認
- APIが未完成の状況下でアプリの動作確認
- APIサーバがメンテナンス中である場合を想定した動作確認
大きなレスポンスの改ざんはLLDBではやりづらいため、その場合は素直にCharlesなどを使いましょう。
応用編3:通信速度を遅くする
Network Link Conditionerを使って低速環境の再現をするケースが多いですが、ブレークポイントでもできます。
po Thread.sleep(forTimeInterval: 10)
によりコールバックを遅延させています。
メインスレッドでsleep()
を実行しないように、ブレークポイントの位置には注意が必要です。
この手法は特に以下ケースで有効です。
- 通信中にインジゲータが表示されているか確認
- 通信中にタップやサスペンドレジュームをしても問題が起きないか確認