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.
}

可能是什么问题?

4

1 回答 1

0

您应该详细说明 [SomeClass performActionWithAsyncResponse] 如何完成其​​工作。

假设在主队列的一个块中调用completionWithResult,这将不起作用,因为线程在测试方法完成后结束。在生产环境中并非如此,因为应用程序一直在运行。

通常我使用这样的代码来等待异步调用,这些调用会在测试中回调主队列。

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

您还可以使用一个条件来停止 while 循环,该条件指示异步工作是否已完成,例如使用测试的属性。

有关异步测试模式的更多信息,请参阅这篇文章: 用于单元测试异步队列的模式,该队列在完成时调用主队列

于 2013-09-22T00:07:24.617 回答