ポイントは次の2つ
(1) 意図したタイミングで通知が配信されたかどうか
(2) 配信された通知は意図したものだったか
たとえば addEntryWithInfo:tagName: というメソッドを呼び出すと LKQueueDidAddEntryNotification という通知が送られることをテストする場合を書いてみる。
テスト対象のメソッドの実装イメージはこんな感じ。
- (LKQueueEntry*)addEntryWithInfo:tagName: { : [[NSNotificationCenter defaultCenter] postNotificationName:LKQueueDidAddEntryNotification object:self]; }処理の最後で LKQueueDidAddEntryNotification をポストしている。objectの引数に自身のインスタンスを渡している。これは通知を受け取った時に notification.object として参照できる。
次にこれをテストするコード。
- (void)testDidAddNotification { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didAdd:) name:LKQueueDidAddEntryNotification object:self.queue]; self.calledNotificationName = nil; [self.queue addEntryWithInfo:@"NOTIFY-TEST-1" tagName:nil]; STAssertEqualObjects(self.calledNotificationName, LKQueueDidAddEntryNotification, nil); // (1) [[NSNotificationCenter defaultCenter] removeObserver:self]; }自身を通知対象として _didAdd: メソッドを登録する。その後、addEntryWithInfo:tagName: を呼び出す。これで通知 LKQueueDidAddEntryNotificationが配信される。(1) はその結果の確認。_didAdd: が正しく呼ばれたら (NSString*)self.calledNotificationName に通知名が入っているのでそれを確認する。これでポイントで挙げた「(1) 意図したタイミングで通知が配信されたかどうか」がテストできる。_didAdd: が呼ばれていないと self.calledNotificationNa は nil となるので STAssertEqualsObjects() が失敗する。
次に _didAdd: の実装。
- (void)_didAdd:(NSNotification*)notification { STAssertEqualObjects(notification.name, LKQueueDidAddEntryNotification, nil); STAssertEquals(notification.object, self.queue, nil); self.calledNotificationName = LKQueueDidAddEntryNotification; }ここではポイントで挙げた「(2) 配信された通知は意図したものだったか」を確認している。もし違う通知が届いていたら最初の STAssertEqualObjects() が失敗する。
なお通知は NSRunLoop によって管理されている。この為、通知が配信(POST)された後、通知が届くにはランループが一巡してからになる。ということはテストコードで addEntryWithInfo:tagName: を呼び出した直後の self.calledNotificationName のテストは失敗するはず(_didAdd: が呼ばれていないから)。この為、一旦ランループを一巡させる為に下記を挿入する必要がある。
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];が、実際には不要だった。動作順番を見ていると testDidAddNotification内で addEntryWithInfo:tagName呼び出し -> post LKQueueDidAddEntryNotification -> _didAdd: -> testDidAddNotificationへ復帰、という動きだった。理由は不明だが OCUnit が通知のテストを考慮してそんな作りにしているのだろうか..
関連情報
iphone - OCUnit testing NSNotification delivery - Stack Overflow
addObserver: に NSMutableArray を渡している。POST時にここへ通知が追加されるようなことが書いてあるが初耳。リファレンスには書いてないようだが。。
Responses
Leave a Response