デリゲートのテストは簡単です。コールバック メソッドのテストで ivar を設定し、デリゲート コールバックをトリガーする必要がある後に確認します。
たとえば、Something
プロトコルのデリゲートを使用し、メッセージに応答しSomethingDelegate
てそのデリゲートを送信するクラスがある場合、次のように-something:delegateInvoked:
テストできます。
@interface TestSomeBehavior : SenTestCase <SomethingDelegate>
{
Something *_object;
BOOL _callbackInvoked;
}
@end
@implementation TestSomeBehavior
- (void)setUp {
[super setUp];
_object = [[Something alloc] init];
_object.delegate = self;
}
- (void)tearDown {
_object.delegate = nil;
[_object release];
[super tearDown];
}
- (void)testSomeBehaviorCallingBack {
[_object doSomethingThatShouldCallBack];
STAssertTrue(_callbackInvoked,
@"Delegate should send -something:delegateInvoked:");
}
- (void)something:(Something *)something delegateInvoked:(BOOL)invoked {
_callbackInvoked = YES;
}
@end
ただし、質問の表現方法から、これはすでに理解していると思います。(私は主に他の読者のためにこれを投稿しています。)あなたは実際にはもっと微妙な質問をしていると思います:ランループをスピンする何かなど、後で発生する可能性のあるものをテストするにはどうすればよいですか。私の合図は、睡眠とスレッド化についてのあなたの言及です。
まず、別のスレッドで勝手にメソッドを呼び出すべきではありません。そのように使用しても安全であることが文書化されている場合にのみ、そうする必要があります。その理由は、クラスの内部が何をするかわからないからです。たとえば、実行ループでイベントをスケジュールする場合があります。この場合、別のスレッドでメソッドを実行すると、別の実行ループでイベントが発生します。これにより、クラスの内部状態が台無しになります。
少し時間がかかる可能性のある何かをテストする必要がある場合は、現在の実行ループを実行するだけでこれを行うことができます。これを行うために、上記の個々のテスト メソッドをどのように書き直すかを次に示します。
- (void)testSomeBehaviorCallingBack {
NSDate *fiveSecondsFromNow = [NSDate dateWithTimeIntervalSinceNow:5.0];
[_object doSomethingThatShouldCallBack];
[[NSRunLoop currentRunLoop] runUntilDate:fiveSecondsFromNow];
STAssertTrue(_callbackInvoked,
@"Delegate should send -something:delegateInvoked:");
}
-doSomethingThatShouldCallBack
これにより、現在の実行ループがデフォルト モードで 5 秒間スピンされます。これは、デフォルト モードでメインの実行ループでの作業がスケジュールされることを前提としています。このように動作する API では、使用する実行ループと実行するモードを指定できることが多いため、これは通常は問題ありません-[NSRunLoop runMode:beforeDate:]
。期待している作業が行われる可能性が高くなります。