如何为异步方法编写XCTestCase?

时间:2014-05-23 01:20:46

标签: ios unit-testing asynchronous xctest

我正在为我的一个模型进行单元测试,该模型使用对我的rest api的异步调用。用于请求我的API的方法是这样的:

requestOnComplete:(void(^)())complete onError:(void(^)(NSString* errMsg))fail;

在我的测试用例中:

-(void)testMyApiCall
{
    [myObj requestOnComplete:^{

        XCTAssertTrue(YES,@"Success");

    } onError:^(NSString *errorString) {

        XCTFail(@"Failed.%@", errorString);

    }];
}

正如我所料,由于异步调用,此测试总是通过。有人可以就这个问题提出建议吗?感谢。

2 个答案:

答案 0 :(得分:1)

我使用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;
}

例如

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

答案 1 :(得分:1)

您可以使用lib XCAsyncTestCase XCTestCas异步方法很简单。 例如,您的测试功能就是您的代码:

-(void)testMyApiCall
{
    [myObj requestOnComplete:^{

        [self notify:XCTestAsyncTestCaseStatusSucceeded];

    } onError:^(NSString *errorString) {

        [self notify:XCTestAsyncTestCaseStatusFailed];

    }];
    [self waitForStatus:XCTestAsyncTestCaseStatusSucceeded timeout:10];
}