[英]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.