2015-01-07 4 views
0

데이터 소스 개체에 대한 단위 테스트를 작성하고 있으며 그 개체의 일반 대리자 개체가 있습니다. 이 개체가 수행하는 작업은 특정 웹 서비스에서 일부 데이터를 가져온 다음 대리인에게 다시 전화하여 성공을 알리는 것입니다. 여기에 코드입니다 : OCMock : 스텁이 서명과 일치하지 않음

NSString *validProductId = @"34142977"; 
NSString *validSiteCode = @"someSiteCode"; 
[[dataSourceDelegateMock expect] dataSource:dataSource didFetchProductData:[OCMArg any] forProductWithId:validProductId]; 
[dataSource fetchProductWithId:validProductId andSiteCode:validSiteCode]; 

NSDate *runUntilDate = [NSDate dateWithTimeIntervalSinceNow:networkTimeOut]; 
while ([runUntilDate timeIntervalSinceNow] > 0) { 
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:runUntilDate]; 
} 
[dataSourceDelegateMock verify]; 

지금이 잘 작동하고 모든, 그리고 예상대로 한 네트워크를 10 초 이내에 일부 데이터로 응답으로, 테스트가 성공한다.

나는 네트워킹 코드를 테스트하는 방법이 아니라는 것을 알고 있습니다. 어떤 사람들은 그것을 다르게 할 것이고, 어떤 사람들은 이것을 통합 테스트라고 부르 겠지만, 그것은 내가이 시점에서 관심이있는 것이 아닙니다.

위의 코드는 정상적으로 작동하지만 네트워크가 일반적으로 그보다 훨씬 빠르다는 사실에 관계없이 매 10 초마다 실행됩니다.

지금은 네트워크에서 아직 응답하지 않은 경우 "아직 시간 초과되지 않은 경우"라는 의미의 while 루프에 다른 조건을 추가하려고합니다. 이런 방식으로, 나는 대부분의 시간 동안 훨씬 더 빠르게 테스트를 수행 할 수있었습니다.

NSString *validProductId = @"34142977"; 
NSString *validSiteCode = @"someSiteCode"; 
__block BOOL dataSourceFetchedData = NO; 
[[dataSourceDelegateMock expect] dataSource:dataSource didFetchProductData:[OCMArg any] forProductWithId:validProductId]; 
[[[dataSourceDelegateMock stub] andDo:^(NSInvocation * invocation) { 
    dataSourceFetchedData = YES; 
}] dataSource:dataSource didFetchProductData:[OCMArg any] forProductWithId:[OCMArg any]]; 
[dataSource fetchProductWithId:validProductId andSiteCode:validSiteCode]; 

NSDate *runUntilDate = [NSDate dateWithTimeIntervalSinceNow:networkTimeOut]; 
while ([runUntilDate timeIntervalSinceNow] > 0 && dataSourceFetchedData == NO) { 
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:runUntilDate]; 
} 
[dataSourceDelegateMock verify]; 

분명히 여기에 아이디어는 즉시 대리인 콜백이 모의 위임 객체로 전송로 (didFetchProductData이 ...)이 부울 변수가 설정 될 것입니다 다음과 같이

그래서 나는 테스트를 수정 YES로 설정하면 while 루프가 종료되어 테스트 자체의 지속 시간이 단축됩니다.

마지막으로 문제는 : 내가 무엇을 하든지간에, 런타임시 대리인 콜백에 대해 호출되는 서명과 일치 할 수 없으므로 블록 안에 넣은 내용은 절대로 실행되지 않습니다. 테스트는 계속 진행되지만 더 빠르지는 않습니다.

많은 디버깅 후 validProductId 변수에서 문제를 찾아 냈습니다. 어떤 이유로 나는 이해할 수 없다. 반환 된 값은 메소드를 스터 빙할 때 설정 한 기대와 결코 일치하지 않을 것이다. 내가 어떻게 알아 ? 기대를 nil로 설정하고 데이터 소스가 nil을 반환하도록 강제하면 모든 것이 잘 작동하기 때문입니다.

내가 생각할 수있는 모든 것을 시도 했으므로 도움이 될 것입니다. 이 다시 호출 데이터 소스 방법 : 데이터 소스가 정확히이 전달되는 동일한 productId에 반환되는 참조 않도록

(void) fetchProductWithId:(NSString *)productId andSiteCode:(NSString *)siteCode { 

NSString *urlString = [NSString stringWithFormat:itemApiString,siteCode,productId]; 
NSURL *url = [NSURL URLWithString:urlString relativeToURL:self.baseUrl]; 
[self.requestManager GET:url.absoluteString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    [self.delegate dataSource:self didFetchProductData:responseObject forProductWithId:productId]; 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    [self.delegate dataSource:self didFailFetchProductDataForProductId:productId withError:error]; 
}]; 

}

난 정말 왜 지구상에서 이해할 수없는 예상 된 스텁 방식과 일치하지 않습니다.

대단히 감사합니다.

답변

1

당신은 expectstub을 결합 할 수 있지만 상호 작용은 대부분의 사람들이 기대하지 것입니다. expect는 메소드에 대한 첫 번째 호출을 처리하고 만족되면 비활성화되어 스텁이 추가 호출을 처리 할 수있게합니다.

즉, 예상 할 수있는 동작을 추가 할 수 있으며, 내가 원하는 것으로 믿습니다. like :

[[[dataSourceDelegateMock expect] andDo:^(NSInvocation * invocation) { 
    dataSourceFetchedData = YES; 
}] dataSource:dataSource didFetchProductData:[OCMArg any]] 
0

동일한 방법으로 스터 빙하고 예상 할 수 있습니다. dataSourceFetchedData 변수를 설정하는 블록으로 매개 변수를 검사하는 것과 같은 시도를하고 스텁 된 메소드를 완전히 제거 할 수 있습니다.

[[dataSourceDelegateMock expect] dataSource:dataSource didFetchProductData:[OCMArg checkWithBlock:^BOOL(id obj){ 
    dataSourceFetchedData = YES; 
    return YES; 
}] forProductWithId:validProductId]; 
+0

고맙습니다 만,이 방법은 해결책이지만 해결책이 아닙니다. – FTSwift