Шаблон для модульного тестирования асинхронной очереди, которая вызывает основную очередь по завершении

Это связано с моим предыдущимвопрос, но достаточно отличающийся, чтобы я решил бросить его в новый. У меня есть некоторый код, который выполняет асинхронный вызов в пользовательской очереди, а затем выполняет блок завершения в главном потоке после завершения. Я хотел бы написать модульный тест вокруг этого метода. Мой метод на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");
}

Я создаю семафор, чтобы заблокировать тестирование до завершения асинхронного кода. Это будет прекрасно работать, если мне не потребуется запускать блок завершения в главном потоке. Однако, как отметили несколько человек в вопросе, с которым я связан выше, тот факт, что тест выполняется в главном потоке, а затем я ставлю в очередь блок завершения в главном потоке, означает, что я просто зависну навсегда.

Вызов основной очереди из асинхронной очереди - это шаблон, который я часто вижу для обновления пользовательского интерфейса и тому подобное. У кого-нибудь есть лучший шаблон для тестирования асинхронного кода, который перезванивает в главную очередь?

Ответы на вопрос(6)

Ваш ответ на вопрос