Taz
Taz

Reputation: 1223

OCMock expected notifications were not observed

I'm currently testing a class in my code that fires off notifications. Putting in breakpoints, I can see that the notifications are being fired but I'm getting a crash with the message caught "OCMockTestFailure", "OCMockObserver : 3 expected notifications were not observed."

The code is fairly simple:

// partial mock my object
id partialMock = OCMPartialMock(myObject);

// do some basic method stubbing on my partial mock

// setup an observer
id observerMock = OCMObserverMock();
// register the mock observer to listen for notifications
[[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:@"Notification1" object:[OCMArg any]];
[[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:@"Notification2" object:[OCMArg any]];
[[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:@"Notification3" object:[OCMArg any]];

// set the expectations
[[observerMock expect] notificationWithName:@"Notification1" object:[OCMArg any] userInfo:[OCMArg any]];
[[observerMock expect] notificationWithName:@"Notification2" object:[OCMArg any] userInfo:[OCMArg any]];
[[observerMock expect] notificationWithName:@"Notification3" object:[OCMArg any] userInfo:[OCMArg any]];

// Call the method that fires the notifications
[myObject doSomethingCoolWithCompletionBlock:^ {
    OCMVerifyAll(observerMock); // <---- THROWS EXCEPTION HERE
    [[NSNotificationCenter defaultCenter] removeObserver:observerMock];
}];

....

// Inside MyObject.m
// In the doSomethingCoolWithCompletionBlock
...
if (someCondition)
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"Notification1" object:self];
}
else if (someOtherCondition)
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"Notification2" object:self];
}
else
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"Notifictaion2" object:self userInfo:@{@"ValueKey" : objectToAddToNotification}];
}
...

The test throws and exception on line OCMVerifyAll(observerMock) with the message error: -[MyObjectTests doSomethingCoolTest] : failed: caught "OCMockTestFailure", "OCMockObserver : 3 expected notifications were not observed."

Can anyone with more OCMock experience see what I'm doing wrong here? (I'm fairly new to OCMock)

Thanks

Upvotes: 1

Views: 678

Answers (1)

kpsharp
kpsharp

Reputation: 455

This could very well likely be a race condition. Even if this passes initially, race conditions in tests make them brittle, which means they will annoy you down the road when they fail occasionally and cause you to have to re-run them all.

Completion blocks are not guaranteed to be ran on the same thread as the one you create them on. Thus, it's possible they are being called on a different thread, which immediately allows for a race condition.

So, you need to remove the race condition. Replace your original doSomethingCoolWithCompletionBlock code with this:

[myObject doSomethingCoolWithCompletionBlock:nil];

OCMVerifyAll(observerMock);
[[NSNotificationCenter defaultCenter] removeObserver:observerMock];

EDIT: Based on your comment, there are still other strategies you can use.

Instead of adding an observer where you are expecting the notification to be posted, you can mock out the defaultCenter and expect the call there:

 OCMockObject *mockNotificationCenter = [OCMockObject partialMockForObject:[NSNotificationCenter defaultCenter]];

[[mockNotificationCenter expect] postNotificationName:@"Notification1" object:OCMOCK_ANY];
// etc..

// doSomethingCool code goes here

[mockNotificationCenter verify];

Upvotes: 2

Related Questions