0

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)
      {
        [...]
      }
    }];
  });
});

これを回避する方法はありますか?

4

1 に答える 1