NSURLConnectionを使用した単体テスト
-
03-07-2019 - |
質問
ネットワークを使用するコード(具体的には NSURLConnection
クラス)をテストします。コード( NetworkManager
と呼びましょう)は次のようになります:
- (id) buildConnection
{
// some more code and then:
return [NSURLConnection …];
}
- (void) startNetworkSync
{
id connection = [self buildConnection];
//…
}
単体テストでは、ネットワークを削除したいと思います。 NSURLConnection
オブジェクトをモックに置き換えます。どうすればいいですか?
I’ buildConnection
メソッドをスタブに置き換える NetworkManager
の部分モックを作成しようとしました。問題は、 OCMock によって行われる部分的なモックは、外界からのスタブメッセージのみであるということです。 – startNetworkSync
から buildConnection
を送信すると、スタブではなく元のメソッドが呼び出されます。
また、カテゴリを介して NetworkManager
クラスにモンキーパッチを適用しようとしました。これは機能します。他のコードで buildConnection
メソッドを簡単にオーバーライドし、実際の NSURLConnection
をスタブに置き換えることができます。問題は、テストでスタブ接続を取得できる簡単な方法を見つけられなかったことです–接続は NetworkManager
のプライベート部分です。
次に、 NetworkManager
をサブクラス化し、 buildConnection
メソッドをオーバーライドし、作成された接続のインスタンス変数とアクセサーを追加できます。しかし、これは多くのコードのようです。
これをどのように解決しますか? NetworkManager
クラスの設計をクリーンに保ち、テストで多くの魔法やコードを必要としないソリューションを探しています。
解決
これは、依存性注入が解決するように設計されたものです。代わりに startNetworkSyncWithConnection:(NSURLConnection *)
を使用すると、モック接続でメソッドを簡単にテストできます。クライアントのAPIを変更したくない場合は、 startNetworkSync
をラッパーとして保持し、 [self buildConnection]
を指定して新しいメソッドを呼び出すこともできます。引数。
他のヒント
実際の部分モックをサポートするようにOCMockを変更しました。 GitHubのリポジトリを参照してください。
最近使用した別のソリューションは、ネットワークインターフェイスを完全に抽象化することです。クラスがネットワークからのデータを必要とする場合、おそらくプロトコルとして明示的にモデル化できるサーバーサービスと対話します。
@protocol SomeNetworkService
- (NSArray*) allAvailableFoos;
- (void) insertNewFoo: (Foo*) foo;
@end
そして、実際のHTTP実装とテスト実装ができます。これは、より多くの作業を意味しますが、テスト容易性も大幅に向上します。テストネットワーク層は必要なことを何でも行うことができるため、テストはそれほど脆弱ではなく、はるかに便利です。