XCTestCase オブジェクトの非同期操作に関する問題に直面しています。のチェーンから始めexpectation-waitForExpectation、非同期操作の完了ブロックによって満たされるように、予期されるインスタンスをメソッド パラメーターとして渡すこともありました。以前のように書かれた悪いコードを見ることができず、この方法で試したので、今私は方法を変更しました:
- (void)testThatItGoesToTheRightSport
{
if (! appDelegateInstance.firstTimeLoaded)
{
[self __waitForLoadingAppAndDo:^(BOOL launched)
{
if (launched)
{
[self __goToLiveWithHandler:^(BOOL success) {
if (success)
{
[self __goToLiveSport:[NSNumber numberWithUnsignedInteger:kDefaultSportCode]
handler:^(BOOL success) {
if (! success)
{
XCTFail(@"Test failed");
}
}];
}
}];
}
}];
}
else
{
[self __goToLiveWithHandler:^(BOOL success) {
if (success)
{
[self __goToLiveSport:[NSNumber numberWithUnsignedInteger:kDefaultSportCode]
handler:^(BOOL success) {
if (! success)
{
XCTFail(@"Test failed");
}
}];
}
}];
}
}
__waitForLoadingAppAndDo:として実装された方法で
- (void)__waitForLoadingAppAndDo:(void (^)(BOOL launched))afterBlock
{
if (! afterBlock)
XCTFail(@"No afterBlock");
XCTestExpectation *dataEx = [self expectationForNotification:NOTIFICATION_HOME_LOADED
object:nil
handler:^BOOL(NSNotification *notification) {
[dataEx fulfill];
return YES;
}];
[self waitForExpectationsWithTimeout:SOCKOPT_TIMEOUT handler:^(NSError *error)
{
if (error)
{
XCTFail(@"No data received. %@", [error localizedDescription]);
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
afterBlock(YES);
});
}
}];
}
そして、他の__方法はそれに似ています。明らかに、testThatメソッドはメソッド完了ハンドラーを待機していません。どうすれば改善できますか? また、testThatメソッドを完了まで待機させるにはどうすればよいですか? XCTestExpectation道は?(言わないでね)
追加:それで、それはユニークな方法ですか?
- (void)testThatItGoesToTheRightSport
{
if (! appDelegateInstance.firstTimeLoaded)
{
XCTestExpectation *waitingLoading = [self expectationWithDescription:@"loadingApp"];
[self waitForExpectationsWithTimeout:SOCKOPT_TIMEOUT handler:^(NSError *error) {
if (error)
{
XCTFail(@"After block was not called.");
}
}];
[self __waitForLoadingAppAndDo:^(BOOL launched)
{
if (launched)
{
[self __goToLiveWithHandler:^(BOOL success) {
if (success)
{
[waitingLoading fulfill];
[...]
}
}];
}
}];
ADDING-2 :
で試しました
__block NSError *internalError = nil;
__block XCTestExpectation *finishedTest = [self expectationWithDescription:@"finishedTest"];
dispatch_group_t asyncGroup = dispatch_group_create();
if (! appDelegateInstance.firstTimeLoaded)
{
dispatch_group_enter(asyncGroup);
[self __waitForLoadingAppAndDo:^(BOOL launched) {
if (! launched)
{
internalError = [TestUtilities notLoadedAppError];
}
dispatch_group_leave(asyncGroup);
}];
dispatch_group_enter(asyncGroup);
[self __goToLiveWithHandler:^(BOOL success) {
if (! success)
{
internalError = [NSError errorWithDomain:@"goLive"
code:-1
userInfo:@{NSLocalizedDescriptionKey : @"Errore apertura Live"}];
}
dispatch_group_leave(asyncGroup);
}];
dispatch_group_notify(asyncGroup, dispatch_get_main_queue(), ^{
[finishedTest fulfill];
});
ただし、グループは完了ブロックを待たずに非同期で呼び出されます。例: OP1が最初に開始され、OP1完了ブロックでOP2が開始されることを期待しています。
ADDING-3 : で別のアプローチを使用しましたdispatch_semaphore。気に入っていますが、交換したいものがあります。シグナルを待つ場合、メインスレッドをブロックしているためdispatch_async、次のwaitコマンドを実行する必要があります。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
dispatch_semaphore_wait(loadedApp, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_main_queue(), ^{
[self __goToLiveWithHandler:^(BOOL success) {
if (success)
{
[...]
}
}];
});
});
これを回避する方法はありますか?