Oct 30th, 2012 iOS, unit test Obj-C 單元測試非同步連線 使用 Xcode 的 OCUnit 來做單元測試網路連線時,由於 OCUnit 不會等 block 執行,所以會直接跳到 pass。一般正常作法應該是用 mock object 來測試,不過總有要實際測試真實連線的時候。這時可以使用以下的 snippet: - (void)testLogin { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [[miiiCasaServer getServer] login:@"test@example.com" andPassword:@"password" success:^(AFHTTPRequestOperation *operation, id responseObject) { assertThat(responseObject[@"status"], is(@"ok")); dispatch_semaphore_signal(semaphore); } failure:nil]; while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; dispatch_release(semaphore); // You don't need this if your deployment target >= 6.0 and ARC enabled. } - (void)testLoginFail { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [[miiiCasaServer getServer] login:@"test@example.com" andPassword:@"wrongpassword" success:nil failure:^(AFHTTPRequestOperation *operation, NSError *error) { assertThat([[error userInfo] objectForKey:@"errmsg"], containsString(@"incorrect")); assertThatInteger([error code], equalToInt(401)); dispatch_semaphore_signal(semaphore); }]; while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; dispatch_release(semaphore); // You don't need this if your deployment target >= 6.0 and ARC enabled. }