未观察到 OCMock 预期的通知

OCMock expected notifications were not observed

我目前正在我的代码中测试一个 class 来触发通知。放置断点,我可以看到通知已被触发,但我遇到了崩溃消息 caught "OCMockTestFailure", "OCMockObserver : 3 expected notifications were not observed."

代码相当简单:

// 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}];
}
...

OCMVerifyAll(observerMock) 上的测试抛出异常,消息为 error: -[MyObjectTests doSomethingCoolTest] : failed: caught "OCMockTestFailure", "OCMockObserver : 3 expected notifications were not observed."

任何有更多 OCMock 经验的人都可以看到我在这里做错了什么吗? (我对 OCMock 还很陌生)

谢谢

这很可能是竞争条件。即使这最初通过了,测试中的竞争条件也会使它们变得脆弱,这意味着当它们偶尔失败时它们会在路上惹恼你并导致你不得不 re-run 它们全部。

完成块不保证运行运行与创建它们的线程在同一线程上。因此,它们有可能在不同的线程上被调用,这会立即导致竞争条件。

因此,您需要删除竞争条件。将原来的 doSomethingCoolWithCompletionBlock 代码替换为:

[myObject doSomethingCoolWithCompletionBlock:nil];

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

编辑:根据您的评论,您还可以使用其他策略。

您可以模拟 defaultCenter 并期望在那里调用:

,而不是在您期望发布通知的地方添加观察者
 OCMockObject *mockNotificationCenter = [OCMockObject partialMockForObject:[NSNotificationCenter defaultCenter]];

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

// doSomethingCool code goes here

[mockNotificationCenter verify];