5

Websocket への接続を処理するためにSocketRocketライブラリを使用しています。問題なく接続されますが、最初に WS 接続を待機する必要があるいくつかの単体テストを実行しようとしています。WS が接続されたことを確認する唯一の方法はデリゲート メソッドを使用することであるため、このプロセスを同期化するのに問題があります。単体テストのsetupメソッドで、単純に WS 接続を作成してからtearDown閉じるようにしたいと考えています。

Websocket クラスに 2 種類の接続メソッドを実装しました。最初の 2 つはかなり基本的なもので、期待どおりに動作することを確認しました。最後の 1 つは、主にテスト目的でブロックするようにする私の試みです。私はそれを機能させることができず、永遠に待つことになるので、それは私の側の概念的な誤解だと思います.

私の大きな疑問は、テスト ケースで実行を停止して、デリゲートへのリターン コールを待機するにはどうすればよいかということだと思います。テスト ケースで発生する問題は、完了ブロックですべてのテストを実行できないことです。テスト メソッドは、これを成功と見なしてプログラムを終了します。

- (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);
    }
}
4

1 に答える 1

4

セマフォがシグナルを受け取るのを待っている間、メイン スレッドはブロックされるため、コードはまったく実行できません。CFRunLoopRun()ライブラリが runloop システムと統合されている場合は、セマフォを待機する代わりに、を使用して runloop を実行できます。準備ができたコールバックから、 を使用して実行ループを停止できますCFRunLoopStop( CFRunLoopGetMain() )

于 2013-02-17T13:56:34.770 に答える