2016-06-15 6 views
0

を行うまで、私はNSThreadを継承MyServiceクラスを有するセレクタを実行する機能をテストし、待つ:ユニットがが

ヘッダ:

@interface MyService : NSThread { 
    -(void) startMe; 
    -(void) doTask; 
    ... 
} 

実装:

@implementation MyService 
    -(void)startMe { 
    [self start]; 
    } 
    -(void) doTask { 
    [self performSelector:@selector(checkData:) onThread:self withObject:nil waitUntilDone:YES]; 
    } 

    -(void) checkData { 
    ... 
    // NOTE: dataChecked is an instance variable. 
    dataChecked = YES; 
    } 
@end 

私がしたいです上記の-(void)doTaskをユニットテストし、-(void)checkDataが実際に呼び出されたことを確認してください。

-(void) testCheckData { 
    // partial mock MyService 
    id myService = [OCMockObject partialMockForObject:[MyService getInstance]]; 
    [myService startMe]; 

    // function to test 
    [myService doTask]; 

    // I wait 2 seconds for checkData to finish its work 
    dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)); 
    dispatch_after(delayTime, dispatch_get_main_queue(), ^(void){ 
     // When running this test case, these code is never called & test passed successfully, WHY? 
     NSLog(@"Check if checkData does its work"); 
     XCTAssertTrue([self isDataChecked]); 
    }); 
} 

つの質問:

Q1私はMyService &は、以下の方法を試してみました、部分的にモックにOCMock libraryを使用しています。あなたは上記を参照したように、私のテストケースでは、私が2秒は、その結果を主張し、実行され-(void)checkDataを期待して待ち-(void)doTask & を呼び出しますが、テストケースを実行しているとき、それは渡さdispatch_after(...) &テスト中にブロックを実行しません。ブロックを実行しないのはなぜですか?

Q2。 NSObject#performSelector:onThread:withObject:waitUntilDone:を呼び出す-(void)doTaskのような関数を単体テストする正しい方法は何ですか?

+0

'XCTestExpectation'と' waitForExpectationsWithTimeout: 'を使う必要があります。ここではかなり良い説明です。https://www.bignerdranch.com/blog/asynchronous-testing-with-xcode-6/ – sbarow

+0

はタイムアウトパラメータです秒またはミリ秒で? –

+0

正しくリコールすれば数秒です。 – sbarow

答えて

0

Q1

あなたはそれをテスト可能にするためにdoTaskを変更できない場合は、テストが完了するのを待つXCTestExpectationを使用する必要があります。また、あらかじめ設定された時間を待つ代わりに、各繰り返しで変数を確認しながらビジーループを行う必要があります。妥当な時間が経過すると、障害が発生する可能性があるため、タイムアウトを設定できます。

// setup expectation  
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    while (dataChecked == NO); 
    // signal expectation 
}); 

// wait for expectation 

Q2

あなたは成功し、それをテストするためにメソッドの実装を知っている必要があります場合は、ユニットテストのための良い候補ではありません。テストされるメソッドが他のメソッドをどのように呼び出すかは関係ありません。副作用が同期または非同期で完了した場合のみ重要です。

+0

私はQ1で提案したことをやったが、設定した秒数に関わらず、待っている部分が待っていなくてもすぐに復帰する。しかし、私が "waitForExpectationsWithTimeout"部分にブレークポイントを設定し、continueボタンを押すと、それは待っています。どんな考え? –

+0

私はこの問題について新しい質問をしました。ここを見てください:http://stackoverflow.com/questions/37845892/unit-test-async-function-by-using-xctestexpectation-but-it-doesnt-wait-のために –

関連する問題