2013-09-21 28 views
0

嘗試將TDD應用於異步代碼時,我發現在部署目標中工作的代碼在測試目標中無效。 的這個問題的一個例子,我發現使用CLLocationManager:異步代碼在測試目標和部署目標中的不同行爲

- (void)testReceivingLocation 
{ 
    locationManager = [[CLLocationManager alloc] init]; 
    locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
    locationManager.delegate = self; 
    locationManager.pausesLocationUpdatesAutomatically = NO; 
    if ([CLLocationManager locationServicesEnabled]) 
    { 
     [locationManager startUpdatingLocation]; 
    } 
    startLocation = nil; 

    NSDate *until = [NSDate dateWithTimeIntervalSinceNow:10]; 
    while ([until timeIntervalSinceNow] > 0) 
    { 
     [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
           beforeDate:until]; 
    } 
    XCTAssert(alreadyReceivedLocation, @"Location wasn't received."); 
} 

-(void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
      fromLocation:(CLLocation *)oldLocation 
{ 
    alreadyReceivedLocation = true; 
    // Never actually get there. 
} 

可以採取什麼問題嗎?

回答

0

您應該詳細說明[SomeClass performActionWithAsyncResponse]如何完成其​​工作。

假設在主隊列的塊中調用了completionWithResult,這將不起作用,因爲線程在測試方法結束後結束。生產中並非如此,因爲應用程序一直在運行。

通常我使用類似這樣的代碼來等待在測試中回調主隊列的異步調用。

NSDate *until = [NSDate dateWithTimeIntervalSinceNow:30]; 
while ([loopUntil timeIntervalSinceNow] > 0) 
{ 
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
          beforeDate:until]; 
} 

你也可以停止與指示是否異步工作完成後,使用測試例如一個屬性的條件while循環。

看到這個職位更多有關異步測試模式: Pattern for unit testing async queue that calls main queue on completion

+0

感謝指針!我用我使用的具體方法更新了問題,並嘗試使用您的代碼而不是sleep()。不幸的是,沒有任何改變... – Sergey

+0

啊,CLLoactionManager我敢打賭,模擬器中沒有任何位置更新。你可以嘗試在GPS定位設備上運行測試嗎? CLLocationManager在模擬器中的行爲有點不同。 – sofacoder