1

基本的な文字列トークンまたはエラー メッセージを返すために、いくつかの 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];
}

これを実際のエンドポイントに配線するまではすべて順調でした-以下のようにコールバックを変更しない限り、それを見つけるためだけに-両方のコールバックを呼び出していました(私が望んでいたものではありません)

- (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. を入れた場合、プロダクションコードが条件付きで失敗するのはなぜですか(ただし、シミュレーターで実行しているときに値をNSLogするとき!= [NSNull null]以外は何も取得できないようです?<null>

SomeResult オブジェクトでは、トークン/エラー プロパティが次のように表示されることに注意してください。

@interface SomeResult : NSObject

@property (strong, nonatomic) NSString *token;
@property (strong, nonatomic) NSString *error;

@end
4

1 に答える 1

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サービスやサードパーティのパーサーを扱っている場合は、防御的にコーディングすることをお勧めします。あなたは両方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にすることもできます。最初にエラーをテストし、エラーがある場合はトークンを設定しないか、トークンを取得した場合はエラーを無視します。両方のコールバックを呼び出したくない場合は、コードパスでそれを不可能にします。

于 2012-06-21T16:07:49.150 に答える