Frage

Sorry for the noob question, but I'm trying to test a connection, but I'm not able do verify the return of the request, because the test ends before the completion handler have a chance to execute. To ilustrate:

-(void)testConnection
{

    [[Conector sharedInstance] performAsynchronousRequestWithServerRequest:_srvRequest completionHandler:^(RequestAsynchronousStatus finishStatus, NSData *data) {
        if (finishStatus == RequestAsynchronousOK){
            _data = data;
            NSLog(@"Data OK");
        }
    }];

    XCTAssertNotNil(_data, @"Data was nil");

}

When I try to assert, _data will always be nil, because the completion handler wasn't executed yet. There is a mechanism to force the test to wait until I have some response from the sendAsynchronousRequest: method. Thanks in advance.

War es hilfreich?

Lösung

This looks like exactly what you need:

XCAsyncTestCase: Asynchronous capable SenTestCase subclass.

Basically, you should write your test like this:

- (void)testConnection
{
    [[Conector sharedInstance] performAsynchronousRequestWithServerRequest:_srvRequest completionHandler:^(RequestAsynchronousStatus finishStatus, NSData *data) {
        if (finishStatus == RequestAsynchronousOK)
        {
            _data = data;
            [self notify:XCTAsyncTestCaseStatusSucceeded];
            NSLog(@"Data OK");
        }
    }];

    [self waitForTimeout:10];

    XCTAssertNotNil(_data, @"Data was nil");
}

Notice the waitForTimeout: call and the notify: calls. 10 seconds should be enough for the test, though it would depend on the request itself.

You could even get more specific and wait for a certain status, like so:

[self waitForStatus: XCTAsyncTestCaseStatusSucceeded timeout:10];

This way, if the connection fails to notify the XCTAsyncTestCaseStatusSucceeded status, the wait call will timeout and your test would fail (as it should).

Andere Tipps

Here's another alternative, XCAsyncTestCase based upon the GHUnit version:

https://github.com/iheartradio/xctest-additions

Usage is the same, just import and subclass XCAsyncTestCase.

@implementation TestAsync
- (void)testBlockSample
{
    [self prepare];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(){
        sleep(1.0);
        [self notify:kXCTUnitWaitStatusSuccess];
    });
    // Will wait for 2 seconds before expecting the test to have status success
    // Potential statuses are:
    //    kXCTUnitWaitStatusUnknown,    initial status
    //    kXCTUnitWaitStatusSuccess,    indicates a successful callback
    //    kXCTUnitWaitStatusFailure,    indicates a failed callback, e.g login operation failed
    //    kXCTUnitWaitStatusCancelled,  indicates the operation was cancelled
    [self waitForStatus:kXCTUnitWaitStatusSuccess timeout:2.0];
}

This is now included in XCode 6:

Obj-C example here:

XCTest and asynchronous testing in Xcode 6

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top