例えば、AFHTTPClient を継承したカスタムクライアントがあるとする。
#import <Foundation/Foundation.h> #import <AFNetworking/AFHTTPClient.h> @interface TodoClient : AFHTTPClient - (void)getTodoList:(void(^)(NSArray*))success failure:(void(^)(NSError*))failure; @end
#import "TodoClient.h" @implementation TodoClient - (void)getTodoList:(void (^)(NSArray*))success failure:(void (^)(NSError*))failure { [self getPath:@"todo/" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { NSArray *array = (NSArray*)responseObject; NSArray *todos = [array map:^id(id item) { return [Todo todoWithDictionary:(NSDictionary*)item]; }]; success(todos); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { failure(error); }]; } @end
カスタムクライアントのユニットテストを書きたい。 でも、呼び出す Web API はまだ完成していない。 そんなときは OCMock の出番。
getPath に期待する値が渡されたかチェックすればいい。 ついでに、引数で渡された Blocks にダミーのデータを渡してしまえ。
#import <SenTestingKit/SenTestingKit.h> #import "TodoClient.h" @interface TodoClientTests : SenTestCase @property (nonatomic) TodoClient *client; @property (nonatomic) id mock; @end
#import "TodoClientTests.h" #import <OCMock/OCMock.h> @implementation TodoClientTests - (void)setUp { self.client = [[TodoClient alloc] init]; // 既存のインスタンスをつかってモックを作成 self.mock = [OCMockObject partialMockForObject:self.client]; } - (void)tearDown { self.client = nil; self.mock = nil; } - (void)testGetTodoList { // getPath の振る舞いを差し替える [[[self.mock expect] andDo:^(NSInvocation *invocation) { void (^successBlock)(AFHTTPRequestOperation *operation, id responseObject) = nil; // atIndex には本来の引数のインデックス(1~) + 1 を指定する [invocation getArgument:&successBlock atIndex:4]; successBlock(nil,@[@{ @"name":@"Test", @"description":@"Test Todo" }]); }] getPath:@"todo/" parameters:nil success:[OCMArg any] failure:[OCMArg any]]; [self.mock getTodoList:^(NSArray *todos) { Todo *todo = [todos objectAtIndex:0]; STAssertEqualObjects(@"Test", todo.name, @"match"); STAssertEqualObjects(@"Test Todo", todo.description, @"match"); } failure:nil]; [self.mock verify]; } @end
getArgument:atIndex に指定するインデックスがややこしい。 ここ嵌りポイント。
引数に Blocks を受け取るメソッドのテストは、この方法でほとんど書けた。