Skip to content

Instantly share code, notes, and snippets.

@cbess
Last active December 18, 2015 20:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbess/5843930 to your computer and use it in GitHub Desktop.
Save cbess/5843930 to your computer and use it in GitHub Desktop.
Asynchronous Unit Testing - Have your Test Case inherit from it to utilize it - ref: https://gist.github.com/andrewroycarter/2254570 License: BSD 3-Clause
//
// CBAsyncTestCase.h
//
// Created by Christopher Bess
//
#import <SenTestingKit/SenTestingKit.h>
@interface CBAsyncTestCase : SenTestCase
/**
* Begins the async operation watch.
* @discussion Call before async operation begins.
*/
- (void)beginAsyncOperation;
/**
* Finishes the async operation watch, call to complete operation and prevent timeout.
*/
- (void)finishedAsyncOperation;
/**
* Waits for the async operation to finish or returns as a timeout.
* @return YES if the async operation timeout interval is exceeded, NO if the
* async operation finished.
*/
- (BOOL)waitForAsyncOperationOrTimeoutWithInterval:(NSTimeInterval)interval;
- (BOOL)waitForAsyncOperationOrTimeoutWithDefaultInterval; // timeout: 10secs
- (void)assertAsyncOperationTimeout; // uses default interval
@end
//
// CBAsyncTestCase.m
//
// Created by Christopher Bess
//
#import "CBAsyncTestCase.h"
@implementation CBAsyncTestCase {
dispatch_semaphore_t _networkSemaphore;
BOOL _didTimeout;
}
- (void)beginAsyncOperation
{
_didTimeout = NO;
_networkSemaphore = dispatch_semaphore_create(0);
}
- (void)finishedAsyncOperation
{
_didTimeout = NO;
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeoutAsyncOperation) object:nil];
dispatch_semaphore_signal(_networkSemaphore);
}
- (BOOL)waitForAsyncOperationOrTimeoutWithDefaultInterval
{
return [self waitForAsyncOperationOrTimeoutWithInterval:10];
}
- (BOOL)waitForAsyncOperationOrTimeoutWithInterval:(NSTimeInterval)interval
{
[self performSelector:@selector(timeoutAsyncOperation) withObject:nil afterDelay:interval];
// wait for the semaphore to be signaled (triggered)
while (dispatch_semaphore_wait(_networkSemaphore, DISPATCH_TIME_NOW))
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
return _didTimeout;
}
- (void)timeoutAsyncOperation
{
_didTimeout = YES;
dispatch_semaphore_signal(_networkSemaphore);
//STFail(@"Async operation timed out."); // auto-fail
}
- (void)assertAsyncOperationTimeout
{
STAssertFalse([self waitForAsyncOperationOrTimeoutWithDefaultInterval], @"timed out");
}
@end
// This Test Case class uses CBAsyncTestCase as the base class
- (void)testNetworkStuff
{
[self beginAsyncOperation];
NSString *identifier = @"777";
[_networkManager fetchStuffWithID:identifier completion:^(NSArray *results, NSError *error) {
STAssertNil(error, @"error occurred: %@", error);
STAssertTrue(results.count, @"no results");
[self finishedAsyncOperation];
}];
// waits for async operation or timeout and fail assertion
[self assertAsyncOperationTimeout];
}
@cbess
Copy link
Author

cbess commented Jun 30, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment