簡體   English   中英

在后台線程上調用XCTestExpectation的方法是否安全?

[英]Is it safe to call XCTestExpectation fulfill method on background thread?

我在很多測試中使用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的完成塊(或者至少提供一種在同一線程上一致地回調的方法),您可以使用GCD輕松執行此操作。

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

或使用NSOperationQueue mainQueue

- (void)doSomethingAsyncInBackgroundWithSuccess:(void (^)(void))completion;
{
  [NSOperationQueue.mainQueue addOperationWithBlock:^{
    completion();
  }];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM