iRSSの日記

はてなダイアリーiRSSの日記の続き

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 へ制御が戻る。