2013-09-30 6 views
9

난 다음이 코드로 AFNetworkingJSON 데이터를 검색하는 GET 요청을 오전에 :어떻게 단위 테스트 AFNetworking 요청

 NSURL *url = [NSURL URLWithString:K_THINKERBELL_SERVER_URL]; 
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; 
    Account *ac = [[Account alloc]init]; 
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET" path:[NSString stringWithFormat:@"/user/%@/event/%@",ac.uid,eventID] parameters:nil]; 

    AFHTTPRequestOperation *operation = [httpClient HTTPRequestOperationWithRequest:request 
                      success:^(AFHTTPRequestOperation *operation, id responseObject) { 
                       NSError *error = nil; 
                       NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:&error]; 
                       if (error) { 
                       } 

                       [self.delegate NextMeetingFound:[[Meeting alloc]init] meetingData:JSON]; 

                      } 
                      failure:^(AFHTTPRequestOperation *operation, NSError *error){ 
                      }]; 
    [httpClient enqueueHTTPRequestOperation:operation]; 

것은 내가이 데이터를 기반으로 단위 테스트를 만들려하지만입니다 난 테스트가 실제로 요청을 원하지 않습니다. 나는 미리 정의 된 구조가 응답으로 반환되기를 원한다. 나는 단위 테스트에 대해 다소 새로운 것이지만, OCMock의 약간을 찔렀다. 그러나이를 관리하는 방법을 알지 못한다.

+0

[Nocilla] (https://github.com/luisobo/Nocilla)를보고 싶을 수도 있습니다. 기존 NSURLConnections에 쉽게 연결하여 동작을 정의 할 수 있습니다. – mAu

답변

12

몇 가지 질문에 대한 의견입니다. 우선, AFHTTPClient를 직접 작성하기 때문에 코드를 테스트하기가 어렵습니다. 나는 그것이 단지 표본이기 때문에 그것이 맞는지는 모르겠지만, 대신 그것을 주입해야한다. (아래 샘플을 보아라.)

둘째, 요청을 작성한 다음 AFHTTPRequestOperation을 작성한 다음이를 대기열에 추가합니다. 이것은 괜찮지 만 AFHTTPClient 메소드 인 getPath : parameters : success : failure :를 사용하여 동일한 결과를 얻을 수 있습니다.

제안 된 HTTP 스터 빙 도구 (Nocilla)에 대한 경험이 없지만 NSURLProtocol을 기반으로합니다. 어떤 사람들은이 방법을 사용한다는 것을 알고 있지만 다음과 같은 코드에서 보듯이 내 자신의 스텁 된 응답 객체를 만들고 http 클라이언트를 조롱하는 것을 선호합니다.

리트리버는 우리가 AFHTTPClient를 주입하는 곳에서 테스트하고자하는 클래스입니다. 일을 간단하고 쉽게 테스트 할 수 있기 때문에 직접 사용자 ID와 이벤트 ID를 전달합니다. 그런 다음 다른 곳에서이 방법에 accout UID 값을 통과 할 것 등등 ... 헤더 파일은 다음과 유사합니다 :

#import <Foundation/Foundation.h> 

@class AFHTTPClient; 
@protocol RetrieverDelegate; 

@interface Retriever : NSObject 

- (id)initWithHTTPClient:(AFHTTPClient *)httpClient; 

@property (readonly, strong, nonatomic) AFHTTPClient *httpClient; 

@property (weak, nonatomic) id<RetrieverDelegate> delegate; 

- (void) retrieveEventWithUserId:(NSString *)userId eventId:(NSString *)eventId; 

@end 


@protocol RetrieverDelegate <NSObject> 

- (void) retriever:(Retriever *)retriever didFindEvenData:(NSDictionary *)eventData; 

@end 

실행 파일 :

#import "Retriever.h" 
#import <AFNetworking/AFNetworking.h> 

@implementation Retriever 

- (id)initWithHTTPClient:(AFHTTPClient *)httpClient 
{ 
    NSParameterAssert(httpClient != nil); 

    self = [super init]; 
    if (self) 
    { 
     _httpClient = httpClient; 
    } 
    return self; 
} 

- (void)retrieveEventWithUserId:(NSString *)userId eventId:(NSString *)eventId 
{ 
    NSString *path = [NSString stringWithFormat:@"/user/%@/event/%@", userId, eventId]; 

    [_httpClient getPath:path 
       parameters:nil 
       success:^(AFHTTPRequestOperation *operation, id responseObject) 
    { 
     NSDictionary *eventData = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:NULL]; 
     if (eventData != nil) 
     { 
      [self.delegate retriever:self didFindEventData:eventData]; 
     } 
    } 
       failure:nil]; 
} 

@end 

그리고 테스트 : 의견을

#import <XCTest/XCTest.h> 
#import "Retriever.h" 

// Collaborators 
#import <AFNetworking/AFNetworking.h> 

// Test support 
#import <OCMock/OCMock.h> 

@interface RetrieverTests : XCTestCase 

@end 

@implementation RetrieverTests 

- (void)setUp 
{ 
    [super setUp]; 
    // Put setup code here; it will be run once, before the first test case. 
} 

- (void)tearDown 
{ 
    // Put teardown code here; it will be run once, after the last test case. 
    [super tearDown]; 
} 

- (void) test__retrieveEventWithUserIdEventId__when_the_request_and_the_JSON_parsing_succeed__it_calls_didFindEventData 
{ 
    // Creating the mocks and the retriever can be placed in the setUp method. 
    id mockHTTPClient = [OCMockObject mockForClass:[AFHTTPClient class]]; 

    Retriever *retriever = [[Retriever alloc] initWithHTTPClient:mockHTTPClient]; 

    id mockDelegate = [OCMockObject mockForProtocol:@protocol(RetrieverDelegate)]; 
    retriever.delegate = mockDelegate; 

    [[mockHTTPClient expect] getPath:@"/user/testUserId/event/testEventId" 
          parameters:nil 
          success:[OCMArg checkWithBlock:^BOOL(void (^successBlock)(AFHTTPRequestOperation *, id)) 
    { 
     // Here we capture the success block and execute it with a stubbed response. 
     NSString *jsonString = @"{\"some valid JSON\": \"some value\"}"; 
     NSData *responseObject = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; 

     [[mockDelegate expect] retriever:retriever didFindEventData:@{@"some valid JSON": @"some value"}]; 

     successBlock(nil, responseObject); 

     [mockDelegate verify]; 

     return YES; 
    }] 
          failure:OCMOCK_ANY]; 

    // Method to test 
    [retriever retrieveEventWithUserId:@"testUserId" eventId:@"testEventId"]; 

    [mockHTTPClient verify]; 
} 

@end 

마지막 것은 AFNetworking 2.0 버전은 사용자의 요구 사항에 대해 설명합니다 경우 사용을 고려 이렇게 출시된다는 점이다.