Colin Wheeler
Colin Wheeler

Reputation: 3343

Mocking NSNotificationCenter with OCMock sometimes fails unless a delay is added

Mocking NSNotificationCenter sometimes may fail if a delay is not introduced apparently. I created a simple test project where I added a single test to test notifications

id mock = [OCMockObject observerMock];
[[NSNotificationCenter defaultCenter] addMockObserver:mock name:kMyNotification object:nil];

[[mock expect] notificationWithName:kMyNotification object:[OCMArg any] userInfo:[OCMArg any]];

MyCoolClass *cool = [MyCoolClass new];

[cool methodthatPostsANotification];

//[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];

[mock verify];

[[NSNotificationCenter defaultCenter] removeObserver:mock];

Basically that test periodically fails unless that commented out runloop line is uncommented. But if the line is uncommented it always succeeds as I expect it to. According to apples docs notifications are supposed to be delivered synchronously, but with the behavior I am seeing its acting like its asynchronous. Basically I don't want to add any intentional delays/sleeping to my unit tests just to make sure they are passing. Is there something that could be done to make these tests always pass without adding delaying code?

Upvotes: 0

Views: 1098

Answers (1)

Vincent Zgueb
Vincent Zgueb

Reputation: 1491

OCMock does not work well with asynchronous processes. Usually it is not recommended to use the NSNotificationCenter in unit tests. Instead you should create a basic mock of it and control precisely when to fire your notification to the observers.

It is not that easy but this is mandatory if you really want to isolate the piece of code you need to test and deterministic results.

Upvotes: 1

Related Questions