在Kiwi iOS中测试NSNotification

时间:2015-05-15 17:41:17

标签: objective-c unit-testing nsnotifications kiwi

所以我需要测试是否发布了NSNotification。我尝试了以下代码来窥探这个论点。

[[NSNotificationCenter defaultCenter] stub:@selector(postNotification:)];

__block KWCaptureSpy *notificationSpy = [[NSNotificationCenter 
defaultCenter] captureArgument:@selector(postNotification:) atIndex:0];

[[theValue(notificationSpy.argument.name) should] equal:theValue(SOME_NOTIFICATION)];

但问题在于,因为它是异步的,所以在测试之前并不总是捕获该参数。我无法为notificationSpy.argument.name添加shouldEventually,因为它会在捕获之前抛出NSInternalConsistencyException来访问参数。

我也试过了, [[SOME_NOTIFICATION should] bePosted]; 它也失败了。

2 个答案:

答案 0 :(得分:3)

如果您希望将来某个时间发送通知,则可以使用expectFutureValue()

[[expectFutureValue(((NSNotification*)notificationSpy.argument).name) shouldEventually] equal:@"MyNotification"];

你也不会得到NSInternalConsistencyException例外,因为如果wrapped被包裹在expectFutureValue内,Kiwi似乎可以正常使用尚未解决的间谍。

其他选择将是

  • stub sendNotification:方法并“手动”捕获已发送的通知:

    __block NSString *notifName = nil;
    [[NSNotificationCenter defaultCenter] stub:@selector(postNotification:) withBlock:^id(NSArray *params) {
        NSNotification *notification = params[0];
        notifName = notification.name;
        return nil;
    }];
    [[notifName shouldEventually] equal:@"TestNotification"];
    
  • 编写一个自定义匹配器,注册到通知中心并在该匹配器上断言:

    [[[NSNotificationCenter defaultCenter] shouldEventually] sendNotification:@"MyNotification"]];
    

就个人而言,我会采用自定义匹配器方法,它更优雅,更灵活。

答案 1 :(得分:2)

我可能缺少某些上下文,因为您没有解释正在测试的代码。你发布通知了吗?或者您是否试图断言IOS框架会为您发布通知?无论如何,这是我用你的方法看到的问题:

  1. 您需要运行在postNotification选择器上监视后发布通知的操作,并且在断言spied参数的值之前。根据您发布的代码,目前尚不清楚是否发生这种情况。

  2. 如果确实调用了postNotification方法,这个解决方案应该可以工作。我实际上不认为这是一个异步问题。我经常在defaultCenter上监视postNotificationName:object:userInfo:并且没有特殊的异步处理代码。

  3. 为了检查Kiwi中字符串的相等性,请不要将它们包装在theValue()中。 theValue()用于检查标量属性的相等性。你的断言应该是这样的:

    [[((NSNotification*)notificationSpy.argument).name should] equal:@"myNotificationName"];
    
  4. 如果这对您没有帮助,请提供更多您正在测试的方法代码和完整的测试方法,以及其他任何有用的信息。