Skip to content

Instantly share code, notes, and snippets.

@jonnolen
Last active August 29, 2015 14:01
Show Gist options
  • Save jonnolen/f90668d795ec32461f24 to your computer and use it in GitHub Desktop.
Save jonnolen/f90668d795ec32461f24 to your computer and use it in GitHub Desktop.
Example of mocking [NSNotificationCenter defaultCenter]
@interface DTClassToTest : NSObject{
id notificationObserver;
}
@property (strong, nonatomic) NSNotificationCenter *notificationCenter;
@property (assign, nonatomic) BOOL receivedNotification;
@end
@implementation DTClassToTest
-(id)init{
return [self initWithNotificationCenter:[NSNotificationCenter defaultCenter]];
}
-(id)initWithNotificationCenter:(NSNotificationCenter *)notificationCenter{
if (!(self = [super init])) return self;
_notificationCenter = notificationCenter;
_receivedNotification = NO;
return self;
}
- (void)registerForNotifications{
id __weak wself = self;
notificationObserver = [self.notificationCenter addObserverForName:@"CONTRIVED_NOTIFICATION"
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *n){
DTClassToTest *self = wself;
self.receivedNotification = YES;
}];
}
- (void)dealloc{
[_notificationCenter removeObserver:notificationObserver];
}
@end
@interface DTClassToTestTests : XCTestCase{
DTClassToTest *objectUnderTest;
NSNotificationCenter *testNotificationCenter;
}
@end
// If you can inject notification center into a class for tests, then this is the best way to do this
@implementation DTClassToTestTests
- (void)setUp{
[super setUp];
testNotificationCenter = [NSNotificationCenter new];
objectUnderTest = [[DTClassToTest alloc] initWithNotificationCenter:testNotificationCenter];
}
- (void)test_responds_to_notification_correctly{
[objectUnderTest registerForNotifications];
[testNotificationCenter postNotificationName:@"CONTRIVED_NOTIFICATION" object:nil];
XCTAssertTrue(objectUnderTest.receivedNotification);
}
@end
@interface DTClassToTestTestsTheClassMockWay : XCTestCase{
DTClassToTest *objectUnderTest;
NSNotificationCenter *testNotificationCenter;
id mockCenter;
}
@end
// if there is no injection point, you can use OCMock to mock the defaultCenter class method. but you need to explicitly call
// stopMocking in your test tearDown.
@implementation DTClassToTestTestsTheClassMockWay
- (void)setUp{
[super setUp];
testNotificationCenter = [NSNotificationCenter new];
mockCenter = [OCMockObject niceMockForClass:NSNotificationCenter.class];
[[[[mockCenter stub] classMethod] andReturn:testNotificationCenter] defaultCenter];
objectUnderTest = [DTClassToTest new]; // Will use [NSNotificationCenter defaultCenter];
}
- (void)tearDown{
[mockCenter stopMocking]; //if you omit this line in your tear down, your tests will not finish.
[super tearDown];
}
- (void)test_responds_to_notification_correctly{
[objectUnderTest registerForNotifications];
[testNotificationCenter postNotificationName:@"CONTRIVED_NOTIFICATION" object:nil];
XCTAssertTrue(objectUnderTest.receivedNotification);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment