Безопасно ли вызывать метод выполнения XCTestExpectation в фоновом потоке?

Я использую XCTestExpectation во многих тестах, а иногда (очень случайным образом) некоторые ожидания не выполняются (хотя я уверен, что они должны быть).

Изучая эту проблему, я заметил, что некоторые ожидания выполняются в основном потоке, а некоторые выполняются в фоновом потоке. И пока эти проблемы с теми, которые выполняются в фоновом потоке.

Безопасно ли оправдывать ожидания из фоновой темы? Я не мог найти никакой конкретной информации об этом.

Ниже приведен пример того, как я использую XCTestExpectation :

 __block XCTestExpectation *expectation = [self expectationWithDescription:@"test"]; [self doSomethingAsyncInBackgroundWithSuccess:^{ [expectation fullfill]; }]; [self waitForExpectationsWithTimeout:10.0 handler:^(NSError *error) { expectation = nil; if (error) { NSLog(@"Timeout Error: %@", error); } }]; 

    Он нигде не документирован, что 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 и предоставить приложению локальные «фиктивные» данные.

    Ваши модульные тесты не должны полагаться на сеть, поскольку это переменная.


    Вы должны выполнить блок завершения doSomethingAsyncInBackgroundWithSuccess в основном потоке (или, по крайней мере, обеспечить возможность последовательно doSomethingAsyncInBackgroundWithSuccess в один поток), вы можете легко сделать это с помощью GCD.

     - (void)doSomethingAsyncInBackgroundWithSuccess:(void (^)(void))completion; { dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); } 

    или используйте NSQperationQueue mainQueue

     - (void)doSomethingAsyncInBackgroundWithSuccess:(void (^)(void))completion; { [NSOperationQueue.mainQueue addOperationWithBlock:^{ completion(); }]; } 
    Давайте будем гением компьютера.