Нигде не задокументировано, что XCTestExpectation является потокобезопасным. из-за отсутствия официальной документации по этому вопросу вы можете только догадываться, создавая тестовые примеры:
- (void)testExpectationMainThread;
{
__block XCTestExpectation *expectation = [self expectationWithDescription:@"test"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
NSLog(@"%@", error);
}];
}
- (void)testExpectationStartMainThreadFulfilBackgroundThread;
{
__block XCTestExpectation *expectation = [self expectationWithDescription:@"test"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, kNilOptions), ^{
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
NSLog(@"%@", error);
}];
}
- (void)testExpectationBackgroundThread;
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, kNilOptions);
__block XCTestExpectation *expectation;
dispatch_sync(queue, ^{
expectation = [self expectationWithDescription:@"test"];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), queue, ^{
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
NSLog(@"%@", error);
}];
}
Здесь он не вылетает и не вызывает проблем, однако из-за отсутствия официальной документации, вероятно, безопаснее придерживаться той же очереди для выполнения.
вам действительно следует заглушить метод doSomethingAsyncInBackgroundWithSuccess
и предоставить приложению локальные «фиктивные» данные.
Ваши модульные тесты не должны полагаться на сеть, поскольку она является переменной.
Вы должны выполнять блок завершения doSomethingAsyncInBackgroundWithSuccess
в основном потоке (или, по крайней мере, предоставить способ последовательного обратного вызова в том же потоке), вы можете легко сделать это с помощью GCD.
- (void)doSomethingAsyncInBackgroundWithSuccess:(void (^)(void))completion;
{
dispatch_async(dispatch_get_main_queue(), ^{
completion();
});
}
или используйте NSOperationQueue mainQueue
- (void)doSomethingAsyncInBackgroundWithSuccess:(void (^)(void))completion;
{
[NSOperationQueue.mainQueue addOperationWithBlock:^{
completion();
}];
}
person
Oliver Atkinson
schedule
12.01.2016
XCTestExpectation
, чтобы избежать состояния гонки, присутствующего в приведенном выше коде, но я лично подозреваю, что проблема заключается в другом. Вы можете подтвердить это, временно добавив некоторые операторыNSLog
и просмотрев временные метки, и я подозреваю, что вы обнаружите, что ваш блок тайм-аута ожидания действительно вызывается до вызова блока завершения вашего асинхронного метода. - person Rob   schedule 12.01.2016XCTestExpectation
из фонового потока небезопасно. Весь смыслXCTestExpectation
заключается в запуске асинхронных тестов. - person Peter Schorn   schedule 14.10.2020