2013-02-17 13 views
5

Używam biblioteki SocketRocket do obsługi połączenia z Websocket. Łączy się dobrze, ale próbuję uruchomić kilka testów jednostkowych, które najpierw czekają na połączenie WS. Ponieważ jedynym sposobem, aby się dowiedzieć, że WS połączone jest metodą delegowania, mam problem z synchronizacją tego procesu. Chcę, aby moja jednostka testowała metodę "setup", aby po prostu utworzyć połączenie WS, a następnie tearDown zamknąć.Wstrzymywanie wykonywania, dopóki Websocket łączy

Zaimplementowałem dwa typy metod połączenia dla mojej klasy Websocket. Pierwsze dwa są dość proste i sprawdziłem, że działają zgodnie z oczekiwaniami. Ostatnia to moja próba zablokowania go przede wszystkim w celach testowych. Nie byłem w stanie sprawić, by działało, a to po prostu kończy się czekaniem na zawsze, więc uważam, że to konceptualne nieporozumienie z mojej strony.

Domyślam się, że moim głównym pytaniem jest, w jaki sposób można zatrzymać wykonanie w przypadku testowym, aby poczekać na odwołanie do delegata? Problem pojawiający się w przypadkach testowych polega na tym, że nie mogę po prostu wykonać wszystkich testów w bloku kończącym - metoda testowa traktuje to jako sukces i kończy program.

- (void)connect 
{ 
    DLog(@"Websocket is connecting now"); 
    [_socket open]; 
} 


- (void)connectWithCompletion:(WebsocketConnection)completion 
{ 
    DLog(@"Connecting now..."); 
    [_onConnectBlocksToRun addObject:^{ 
     completion(self.isConnected, self.socket); 
    }]; 
    [_socket open]; 
} 

- (bool)connectBlocking // XXX Doesn't work! 
{ 
    sem = dispatch_semaphore_create(0); 
    [_socket open]; 

    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 
    return _isConnected; 
} 

#pragma mark - Socket rocket delegate 
- (void)webSocketDidOpen:(SRWebSocket *)webSocket 
{ 
    DLog(@"Websocket has opened"); 
    _isConnected = YES; 
    _socket = webSocket; 

    for (void(^block)() in _onConnectBlocksToRun) { 
     block(); 
    } 
    [_onConnectBlocksToRun removeAllObjects]; 

    if (sem) { 
     dispatch_semaphore_signal(sem); 
     dispatch_release(sem); 
    } 
} 

Odpowiedz

4

Podczas oczekiwania na sygnalizowanie semafora główny wątek jest blokowany, więc żaden kod nie może w ogóle działać. Jeśli twoja biblioteka integruje się z systemem runloop, możesz uruchomić runloop używając CFRunLoopRun() zamiast czekać na semaforze. Z gotowego oddzwaniania można następnie zatrzymać runloop przy użyciu CFRunLoopStop(CFRunLoopGetMain()).

+0

Tak !! To działało idealnie i nauczyłem się czegoś nowego. Dzięki! – joslinm