Objective c NSString类型的属性何时为[NSNull null]

Objective c NSString类型的属性何时为[NSNull null],objective-c,ocunit,ocmock,nsnull,Objective C,Ocunit,Ocmock,Nsnull,我正在解析一些json以返回基本字符串标记或错误消息 - (void)callBackWithVerifyHttpResponse:(NSData *)response { SomeResult *result = [self.parser parseVerifyHttpResponseAndReturnResult:response]; if (result.token) { [self.delegate callBackWithToken:result.token]; }

我正在解析一些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];
}
一切都很好,直到我把它连接到一个实际的端点——结果发现,除非我像下面那样修改回调——它调用了两个回调(不是我所希望的)

第二部分问题

  • 为什么我不能写一个测试来证明这一点?每当我将错误或令牌设置为NULL或NSNull时,它都可以正常工作(但这段代码是生产工作所必需的)

  • 如果我将
    !=[NSNull null]
    (但是当我在模拟器中运行时记录值时,我似乎只能得到

  • 请记住,SomeResult对象上的标记/错误属性如下所示

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

    您的原始代码和测试期望令牌或错误为
    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服务和/或第三方解析器可能会微妙地改变其行为时,最好采用防御性编码。您可以同时处理
    nil
    NSNull

    - (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——首先测试错误,如果出现错误,则永远不要设置令牌,或者如果获得令牌,则忽略错误。如果您不想同时调用这两个回调,则在代码路径中设置为不可能

    - (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]; }
    }