如果NSString类型的属性是[NSNull null]

时间:2012-06-21 10:37:56

标签: objective-c ocunit ocmock nsnull

我正在解析一些json以返回基本字符串标记或错误消息。

- (void)callBackWithVerifyHttpResponse:(NSData *)response
{
    SomeResult *result = [self.parser parseVerifyHttpResponseAndReturnResult:response];
    if (result.token) { [self.delegate callBackWithToken:result.token]; }
    if (result.error) { [self.delegate callBackWithError:result.error]; }
}

证明这一点的测试

- (void)testVerifyCallbackInvokesErrorCallbackOnDelegateWhenParserReturnsError
{
    SomeResult *result = [[SomeResult alloc] init];
    result.error = @"fail";
    [[self.delegate expect] callBackWithError:@"fail"];
    [[self.delegate reject] callBackWithToken:OCMArg.any];
    [[[self.parser stub] andReturn:result] parseVerifyHttpResponseAndReturnResult:nil];
    [self.sut callBackWithVerifyHttpResponse:nil];
    [self.delegate verify];
}

- (void)testVerifyCallbackInvokesTokenCallbackOnDelegateWhenParserReturnsToken
{
    SomeResult *result = [[SomeResult alloc] init];
    result.token = @"token";
    [[self.delegate expect] callBackWithToken:@"token"];
    [[self.delegate reject] callBackWithError:OCMArg.any];
    [[[self.parser stub] andReturn:result] parseVerifyHttpResponseAndReturnResult:nil];
    [self.sut callBackWithVerifyHttpResponse:nil];
    [self.delegate verify];
}

一切顺利,直到我把它连接到一个实际的端点 - 只是发现除非我修改了回调,如下面的-it正在调用两个回调(不是我希望的)

- (void)callBackWithVerifyHttpResponse:(NSData *)response
{
    SomeResult *result = [self.parser parseVerifyHttpResponseAndReturnResult:response];
    if (result.token != [NSNull null]) { [self.delegate callBackWithToken:result.token]; }
    if (result.error != [NSNull null]) { [self.delegate callBackWithError:result.error]; }
}

所以2部分问题

  1. 为什么我不能写一个测试来证明这一点?任何时候我将错误或令牌设置为NULL或NSNull它工作正常(但生产工作需要此代码)

  2. 为什么生产代码只有在我放!= [NSNull null]时才会失败条件(但是当我运行它时,我在NSLog值时看起来除了<null>之外什么也看不到模拟器?

  3. 请记住,SomeResult对象上的令牌/错误属性如下所示

    @interface SomeResult : NSObject
    
    @property (strong, nonatomic) NSString *token;
    @property (strong, nonatomic) NSString *error;
    
    @end
    

1 个答案:

答案 0 :(得分:2)

您的原始代码和测试期望令牌或错误为nil,而不是[NSNull null]。据推测,当您针对生产端点运行它时,解析器将值设置为[NSNull null]

这些测试应该通过修改后的代码:

- (void)testVerifyCallbackInvokesErrorCallbackOnDelegateWhenParserReturnsError
{
    SomeResult *result = [[SomeResult alloc] init];
    result.error = @"fail";
    result.token = [NSNull null];
    [[self.delegate expect] callBackWithError:@"fail"];
    [[self.delegate reject] callBackWithToken:OCMArg.any];
    [[[self.parser stub] andReturn:result] parseVerifyHttpResponseAndReturnResult:nil];
    [self.sut callBackWithVerifyHttpResponse:nil];
    [self.delegate verify];
}

- (void)testVerifyCallbackInvokesTokenCallbackOnDelegateWhenParserReturnsToken
{
    SomeResult *result = [[SomeResult alloc] init];
    result.token = @"token";
    result.error = [NSNull null];
    [[self.delegate expect] callBackWithToken:@"token"];
    [[self.delegate reject] callBackWithError:OCMArg.any];
    [[[self.parser stub] andReturn:result] parseVerifyHttpResponseAndReturnResult:nil];
    [self.sut callBackWithVerifyHttpResponse:nil];
    [self.delegate verify];
}

当您处理可以巧妙地改变其行为的Web服务和/或第三方解析器时,防御性编码是很好的。您可以处理nilNSNull

- (void)callBackWithVerifyHttpResponse:(NSData *)response
{
    SomeResult *result = [self.parser parseVerifyHttpResponseAndReturnResult:response];
    if (result.token && result.token != [NSNull null]) { [self.delegate callBackWithToken:result.token]; }
    if (result.error && result.error != [NSNull null]) { [self.delegate callBackWithError:result.error]; }
}

您可能还希望将其设为if / else - 首先测试错误,如果出现错误则不设置令牌,或者如果获得令牌则忽略错误。如果您不希望同时调用这两个回调,则在代码路径中无法进行回调。