I'm using the SocketRocket library to handle connecting to a Websocket. It connects just fine, but I'm trying to run some unit tests that have to first wait on the WS connecting. Since the only way to know that the WS has connected is through its delegate method, I'm having trouble making this process synchronous. I want my unit tests' setup
method to simply create a WS connection and then tearDown
close it.
I've implemented two types of connection methods for my Websocket class. The first two are pretty basic and I've verified that they work as expected. The last one is my attempt at making it blocking primarily for testing purposes. I have not been able to get it working and it just ends up waiting forever, so I believe that's a conceptual misunderstanding on my part.
I guess my big question is how can I stop execution in a test case to wait on a return call to a delegate? The problem arising in test cases is that I can't just do all my tests in the completion block -- the test method sees this just as a success and ends the 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);
}
}
While you are waiting for your semaphore to get signaled the main thread is blocked so no code can run at all. If your library integrates with the runloop system you can run the runloop using CFRunLoopRun()
instead of waiting on your semaphore. From your ready callback you can then stop the runloop using CFRunLoopStop( CFRunLoopGetMain() )
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With