Last week I had to write some unit tests for a class which sent NSNotifications to the default NSNotificationCenter. I wanted to make sure that the instance sent those notifications with correct names, with correct information and in correct order.
The default NSNotificationCenter is basically a global context which is used by many classes. As Miško Hevery points out, global state makes testing hard. So if I decided to be pedantic about avoiding global state and making my code easily testable, I would create a new NSNotificationCenter in a factory and inject it into every class which needs it in each class’ init… method. Then, in unit tests, I could inject my own subclass of NSNotificationCenter which would receive all notifications sent by the instance under test. Then I could examine those notifications and make any checks I need. However, injecting NSNotificationCenter into each class which needs it complicates their init… methods, and it’s probably a bit overkill to require each class which is interested in notifications to retain a notificationcenter in an ivar.
A bit more pragmatic way to record & validate notifications sent by the instance under test is to create a mutable array, register it as an observer of the instance in the default NSNotificationCenter, exercise the instance and then validate the notifications which were catched by the array. Fortunately, NSMutableArray has a method which can act directly as notification callback: the good old -(void)addObject:(id)anObject. For instance:
MyClass *obj = [[[MyClass alloc] init] autorelease]; NSMutableArray *notifications = [NSMutableArray array]; [[NSNotificationCenter defaultCenter] addObserver:notifications selector:@selector(addObject:) name:nil object:obj]; [obj exercise]; STAssertEquals([notifications count], 1u, @"Invalid number of notifications."); STAssertEqualObjects([(NSNotification *)[notifications objectAtIndex:0] name], @"MyClassNotificationName", @"Notification name was invalid.");