简体   繁体   English

在后台线程上调用XCTestExpectation的方法是否安全?

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

I am using XCTestExpectation in a lot of tests and sometimes (very randomly) some expectations are not fulfilled (although I am sure they should be). 我在很多测试中使用XCTestExpectation ,有时(非常随机)某些期望没有实现(虽然我确信它们应该是)。

While investigating this problem I have noticed that some expectations are fulfilled in a main thread and some are fulfilled in a background thread. 在调查这个问题的同时,我注意到在主线程中满足了一些期望,并且在后台线程中实现了一些期望。 And so far these problems are with the ones fulfilled in a background thread. 到目前为止,这些问题都与后台线程中遇到的问题有关。

Is it safe to fulfill expectations from a background thread? 从后台线程满足期望是否安全? I could not find any explicit information about that. 我找不到任何关于此的明确信息。

Below is an example of how I use 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);
    }
}];

It's not documented anywhere that XCTestExpectation is thread-safe. 在XCTestExpectation是线程安全的任何地方都没有记录。 due to there being no official documentation on the matter you can only guess by creating test examples: 由于没有关于此事的官方文档,您只能通过创建测试示例来猜测:

- (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);
  }];

}

Here it does not crash or cause a problem however due to the lack of official documentation it is probably safer to stick to the same queue to fulfil. 在这里它不会崩溃或导致问题,但由于缺乏官方文档,坚持同一队列来实现可能更安全。


you should really be stubbing the method doSomethingAsyncInBackgroundWithSuccess and provide the app with local "dummy" data. 你应该真正存根方法doSomethingAsyncInBackgroundWithSuccess并为应用程序提供本地“虚拟”数据。

Your unit tests should not rely on network as it is something which is variable. 您的单元测试不应该依赖于网络,因为它是可变的。


You should be executing the completion block of doSomethingAsyncInBackgroundWithSuccess on the main thread (or at least provide a way to call back consistently on the same thread), you can easily do this with GCD. 您应该在主线程上执行doSomethingAsyncInBackgroundWithSuccess的完成块(或者至少提供一种在同一线程上一致地回调的方法),您可以使用GCD轻松执行此操作。

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

or use NSOperationQueue mainQueue 或使用NSOperationQueue mainQueue

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 XCTestExpectation在单元测试中正确执行方法调用的时间/位置? - Correct timing/placement of XCTestExpectation fulfill method call in unit tests? 当App是后台时,我们可以在locationManager didEnterRegion方法中调用WebService吗? 如何赚取额外的时间来完成WS电话? - Can we call WebService in locationManager didEnterRegion method when App is background? How to earn extra time to fulfill WS call? 如何在延迟和后台线程中调用方法 - How to call method with delay and in background thread 在后台线程中运行NSTimer以在主线程完成时调用方法 - Run NSTimer in background thread to call method on completion in main thread save:方法是否是线程安全的? - Is the save: method thread-safe? API 违规 - 多次调用 -[XCTestExpectation meet],我该如何解决这个问题 - API violation - multiple calls made to -[XCTestExpectation fulfill], How can i solve this problem 这种初始化单例线程的方法安全吗? - Is this method of initializing singleton thread safe? 后台线程上的调用函数 - call function on background thread 在后台线程中执行 Realm 迁移是否安全? - Is it safe to perform Realm migration in background thread? 将 UIVIew 渲染到后台线程上的图像的安全方法? - Safe way to render UIVIew to an image on background thread?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM