SenTestを使って非同期のテスト
以下のような感じで、うごいているっぽいのだけど、本当にこんなので、よいのか?
↓たぶん、だめみたい。
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
をよぶと、 [mm updateNewsstandIssues];が2重起動されるようにみえる??
だめに見えたのは、バグだった模様です。
なので、以下で大丈夫かも。
@implementation spikeTests - (void)setUp { [super setUp]; // Set-up code here. _isDone = NO; } - (void)tearDown { // Tear-down code here. [super tearDown]; } - (void)testModelManagerUpdateNewsstandIssues { JLNModelManager *mm = [JLNModelManager sharedManager]; STAssertNotNil(mm, @"creted model maneger"); // ISSUEをクリアしてから、テストする。 mm.issueList = nil; STAssertNil(mm.issueList, @"mm.issueList をクリアできていることをテスト"); // ISSUEの更新を実行 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleIssueUpdated:) name:@"issueListUpdated" object:nil]; [mm updateNewsstandIssues]; while (!_isDone) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; NSLog(@"Polling..."); } NSDictionary *issueList = mm.issueList; STAssertEquals([(NSArray *)[issueList objectForKey:@"issue"] count] , (NSUInteger)4, @"4件"); [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void) handleIssueUpdated:(NSNotification*)notification; { _isDone = YES; }
updateNewsstandIssuesメソッドの最後に
[[NSNotificationCenter defaultCenter] postNotificationName:@"issueListUpdated" object:nil userInfo:nil
なふうに、issueListUpdatedをよびだしている。
このnotificationでhandleIssueUpdatedは実行され、_isDoneになり、 while (!_isDone)のループから抜ける仕組み。
runUntilDateについては、以下を参考にさせていただきました。
while 内で一旦 NSRunLoop へ制御を戻してやる。戻すには -[NSRunLoop runUntilDate:] を使う。このメソッドは引数で指定した日時までの間、その場で処理を一時停止し NSRunLoop へ制御を戻す。そして指定の日時がきたら処理を再開する。
NSRunLoop Class Reference先ほどのコードにこんな感じで追加してやる。
self.finished = NO;
while (!self.finished) {
[[NSRunLoop currentRunLoop]
runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
}すると while ループ内でおおよそ 0.5秒間 NSRunLoop へ制御が戻る。