これは私の前の質問に関連していますが、私がそれを新しい質問に投げ込むと思ったほど十分に異なっています。カスタムキューで非同期を実行し、完了時にメインスレッドで完了ブロックを実行するコードがあります。この方法を中心に単体テストを書きたいと思います。私の方法はMyObject
次のようになります。
+ (void)doSomethingAsyncThenRunCompletionBlockOnMainQueue:(void (^)())completionBlock {
dispatch_queue_t customQueue = dispatch_queue_create("com.myObject.myCustomQueue", 0);
dispatch_async(customQueue, ^(void) {
dispatch_queue_t currentQueue = dispatch_get_current_queue();
dispatch_queue_t mainQueue = dispatch_get_main_queue();
if (currentQueue == mainQueue) {
NSLog(@"already on main thread");
completionBlock();
} else {
dispatch_async(mainQueue, ^(void) {
NSLog(@"NOT already on main thread");
completionBlock();
});
}
});
}
安全性を高めるためにメインキューテストを投入しましたが、常にヒットしdispatch_async
ます。私の単体テストは次のようになります。
- (void)testDoSomething {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
void (^completionBlock)(void) = ^(void){
NSLog(@"Completion Block!");
dispatch_semaphore_signal(sema);
};
[MyObject doSomethingAsyncThenRunCompletionBlockOnMainQueue:completionBlock];
// Wait for async code to finish
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_release(sema);
STFail(@"I know this will fail, thanks");
}
非同期コードが完了する前にテストが終了するのをブロックするために、セマフォを作成します。これは、メインスレッドで実行するために完了ブロックを必要としない場合にうまく機能します。ただし、上記のリンク先の質問で2人の人が指摘したように、テストがメインスレッドで実行されてから、メインスレッドの完了ブロックをキューに入れるという事実は、永遠にハングすることを意味します。
非同期キューからメインキューを呼び出すことは、UIなどを更新するためによく見かけるパターンです。メインキューにコールバックする非同期コードをテストするためのより良いパターンを持っている人はいますか?