没有观察到OCMock预期的通知

时间:2016-01-14 15:57:36

标签: ios objective-c unit-testing mocking ocmock

我目前正在我的代码中测试一个触发通知的类。放入断点,我可以看到通知被解雇但我收到了消息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来说还不够新鲜)

由于

1 个答案:

答案 0 :(得分:2)

这很可能是一场竞争。即使这最初通过,测试中的竞争条件也会使它们变得脆弱,这意味着当它们偶尔失败并且导致你必须重新运行它们时,它们会让你烦恼。

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

所以,你需要删除竞争条件。将原始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];