0

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?

Colin Wheeler
  • 3,343
  • 2
  • 21
  • 23

1 Answers1

1

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.

Vincent Zgueb
  • 1,491
  • 11
  • 11
  • so if I am reading your answer correctly, are you suggesting something like this https://gist.github.com/anonymous/9237241 ? – Colin Wheeler Feb 26 '14 at 19:59
  • Yes just use your mock instead of the real notification center and control everything synchronously. That is the idea. – Vincent Zgueb Feb 26 '14 at 20:16