Reputation: 12925
I'm working on a unit test for one of my model which is using asynchronized call to my rest api.The method used to request my API is like this:
requestOnComplete:(void(^)())complete onError:(void(^)(NSString* errMsg))fail;
In my test case:
-(void)testMyApiCall
{
[myObj requestOnComplete:^{
XCTAssertTrue(YES,@"Success");
} onError:^(NSString *errorString) {
XCTFail(@"Failed.%@", errorString);
}];
}
As I expected, this test always pass because of the asynchronized call. Can anybody advise on this issue? Thanks.
Upvotes: 0
Views: 134
Reputation: 5148
You can use lib XCAsyncTestCase It simple to do XCTestCas asynchronized method. Ex as your test function here is your code:
-(void)testMyApiCall
{
[myObj requestOnComplete:^{
[self notify:XCTestAsyncTestCaseStatusSucceeded];
} onError:^(NSString *errorString) {
[self notify:XCTestAsyncTestCaseStatusFailed];
}];
[self waitForStatus:XCTestAsyncTestCaseStatusSucceeded timeout:10];
}
Upvotes: 1
Reputation: 46598
I use these helper functions
BOOL XLCRunloopRunUntil(CFTimeInterval timeout, BOOL (^condition)(void));
#define XLCAssertTrueBeforeTimeout(expr, timeout, format...) \
XCTAssertTrue( (XLCRunloopRunUntil(timeout, ^BOOL{ return expr; })) , ## format )
static inline void XLCRunloopRunOnce()
{
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, YES) == kCFRunLoopRunHandledSource ||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, YES) == kCFRunLoopRunHandledSource);
}
static inline void XLCRunloopRun(CFTimeInterval timeout)
{
CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, NO);
XLCRunloopRunOnce();
}
BOOL XLCRunloopRunUntil(CFTimeInterval timeout, BOOL (^condition)(void)) {
static mach_timebase_info_data_t timebaseInfo;
if ( timebaseInfo.denom == 0 ) {
mach_timebase_info(&timebaseInfo);
}
uint64_t timeoutNano = timeout * 1e9;
uint64_t start = mach_absolute_time();
do {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01, YES);
XLCRunloopRunOnce();
uint64_t end = mach_absolute_time();
uint64_t elapsed = end - start;
uint64_t elapseNano = elapsed * timebaseInfo.numer / timebaseInfo.denom;
if (elapseNano >= timeoutNano) {
return NO;
}
} while (!condition());
return YES;
}
example
-(void)testMyApiCall
{
__block BOOL done = NO;
[myObj requestOnComplete:^{
// XCTAssertTrue(YES,@"Success"); // this line is pointless
done = YES;
} onError:^(NSString *errorString) {
XCTFail(@"Failed.%@", errorString);
done = YES;
}];
XLCAssertTrueBeforeTimeout(done, 1, "should finish within 1 seconds");
}
Upvotes: 1