OCUnit测试NSNotification交付

pgb*_*pgb 12 iphone unit-testing objective-c

对于我正在开发的游戏,我有几个模型类在状态发生变化时触发通知.然后,视图订阅这些通知并对它们作出反应.

我正在使用OCUnit对模型进行单元测试,并希望断言预期的通知已发布.为此,我正在做这样的事情:

- (void)testSomething {
    [[NSNotificationCenter defaultCenter] addObserver:notifications selector:@selector(addObject:) name:kNotificationMoved object:board];

    Board *board = [[Board alloc] init];
    Tile *tile = [Tile newTile];

    [board addTile:tile];

    [board move:tile];

    STAssertEquals((NSUInteger)1, [notifications count], nil);
    // Assert the contents of the userInfo as well here

    [board release];
}
Run Code Online (Sandbox Code Playgroud)

我们的想法是通过调用方法NSNotificationCenter将通知添加到通知中.NSMutableArrayaddObject:

然而,当我运行它时,我看到它addObject:被发送到其他对象(而不是我的NSMutableArray),导致OCUnit停止工作.但是,如果我注释掉一些代码(例如release调用或添加新的单元测试),一切都会按预期开始工作.

我假设这有时间问题,或者NSNotificationCenter以某种方式依赖于运行循环.

有没有建议来测试这个?我知道我可以添加一个setter Board并注入我自己的NSNotificationCenter,但我正在寻找一种更快的方法(也许是如何NSNotificationCenter动态替换它的一些技巧).

pgb*_*pgb 5

发现了问题.测试通知时,您需要在测试后删除观察者.工作代码:

- (void)testSomething {
    [[NSNotificationCenter defaultCenter] addObserver:notifications selector:@selector(addObject:) name:kNotificationMoved object:board];

    Board *board = [[Board alloc] init];
    Tile *tile = [Tile newTile];

    [board addTile:tile];

    [board move:tile];

    STAssertEquals((NSUInteger)1, [notifications count], nil);
    // Assert the contents of the userInfo as well here

    [board release];
    [[NSNotificationCenter defaultCenter] removeObserver:notifications name:kNotificationMoved object:board];
}
Run Code Online (Sandbox Code Playgroud)

如果未能删除观察者,则在测试运行并释放一些局部变量后,通知中心将尝试在运行任何触发相同通知的后续测试时通知这些旧对象.