0

単体テストを書いています。そして、keyWindowを呼び出すため、1つの関数をテストできません

UIWindow* window = [UIApplication sharedApplication].keyWindow;

そして、keyWindow は nil を返します (ウィンドウがありません)。しかし、私は何かを返す必要がありますが、ゼロです。

カテゴリを使用して keyWindow 値を手動で設定しましたが、これは機能しませんでした

@interface UIApplication(UnitTest)
- (id)getKeyWindow;
@end

@implementation UIApplication(UnitTest)
- (id)getKeyWindow
{
    return [self keyWindow];
}
@end

// compiler error: lvalue required as left operand of assignment
[[UIApplication sharedApplication] getKeyWindow] = [[UIWindow alloc] init]; 

私の代わりに何をしますか?

4

3 に答える 3

3

フレームワーク クラスに近づき始めると、Apple はコードのテストを容易にしません。UIApplication は、そのシングルトンの性質と、セットアップ中にフレームワークがインスタンスを作成するという事実のために、特に難しいことがわかりました。このような問題の解決策は、通常、テスト方法によって異なります。たとえば、テストに有効な UIApplication オブジェクトがありますか? OCUnit を使用している場合、テスト ターゲットをアプリケーション バンドルで実行するように設定していない限り、[UIApplication sharedApplication] 自体が nil を返すことがあります (正直なところ、これを機能させることができませんでした)。

1 つのオプションは、これをテストしないことです。ほとんどの場合、メイン ウィンドウとの対話は比較的単純であり、このコードのテストは、独自のコードと同様に UIKit フレームワークをテストしています。これは、コードをどのように構造化したか、この小さな領域をテストせずに (または、より適切にはテスト自動化を行わずに) 残しておくことがどれだけ快適であるか、およびテストを記述することがどれほど難しいかによって決まります。

テストする必要があると判断した UIWindow オブジェクトに関連するコードがある場合は、テスト中に制御できるように機能をカプセル化することをお勧めします。カスタム メソッドから UIWindow オブジェクトを返すアプリの UIApplication のサブクラスを作成することで、これを行うことができます。ウィンドウ プロパティに直接アクセスするのではなく、コードでこのメソッドを使用し、テストでこのメソッドをオーバーライドして、好きなものを返します。

于 2010-11-08T20:11:36.877 に答える
0

アプリケーション デリゲート セッターをスウィズルすることで、デリゲート オブジェクトをモックし、applicationDidBecomeActive などの特定の期待値を検証することができました。

id<UIApplicationDelegate> delegate = [MyCustomDelegate alloc] init];
UIApplication *app = [UIApplication alloc] init];
app.delegate = delegate;
//results in "There can only be one UIApplication" error

その代わり:

@implementation AppDelegateTests {

- (void)testAppDelegate {
     //perform swizzle on [UIApplication class] and method @selector(setDelegate:) with
     //[self class] and at the bottom @selector(swizzledSetDelegate:)

     id<UIApplicationDelegate> delegate = [MyCustomDelegate alloc] init];

     //Here's the magic, this line actually calls [UIApplication setDelegate] and not the swizzledSetDelegate method below. 
     //If you don't understand this, look up how swizzling works and hopefully you can wrap your head around it. The logic is quite mind-bendy.
     [self swizzledSetDelegate:delegate];

     //here set up your mock on the delegate and verify state of things
}

- (void)swizzledSetDelegate:(id<UIApplicationDelegate>)delegate {
     //do nothing
}

}

この例は、私がテストする必要があるものにかなりカスタム化されていることに注意してください。何をモックしたいのか、それが可能かどうかを考える必要があります。

于 2013-08-03T01:47:21.893 に答える