![](/img/trans.png)
[英]Correct timing/placement of XCTestExpectation fulfill method call in unit tests?
[英]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.