iOSでintegration testを書きたいけど、Facebook SDKのログインフローでつまずいてテストが書けない
こういうときに便利!
手段
- categoryで、既存のメソッドを書き換える
-
method_exchangeImplementations
でクラスのメソッドを書き換える
-> categoryで既存のメソッドを書き換えるのが簡単だし分かりやすい
実装方法
- KIFでfacebookログインボタンが押されたときに、Facebookの
openWithBehavior
のメソッドが実行されるか
@interface WelcomeViewController ()
- (IBAction)authenticateAction;
@end
@implementation WelcomeViewController
#pragma mark - IBActions
- (IBAction)authenticateAction
{
self.session = [[FBSession alloc] initWithAppID:kFacebookAppID permissions:kFacebookPermissions urlSchemeSuffix:kFacebookUrlSchemeSuffix tokenCacheStrategy:nil];
[self.session openWithBehavior:FBSessionLoginBehaviorWithNoFallbackToWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
//login code
}];
}
@end
static id mockSession = nil;
@implementation FBSession (UnitTests)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (instancetype)initWithAppID:(NSString *)appID
permissions:(NSArray *)permissions
urlSchemeSuffix:(NSString *)urlSchemeSuffix
tokenCacheStrategy:(FBSessionTokenCachingStrategy *)tokenCachingStrategy {
return mockSession;
}
#pragma clang diagnostic pop
@end
@interface WTDLoginFlowTest : KIFTestCase
@end
@implementation WTDLoginFlowTest
- (void)testSuccessfulLogin
{
mockSession = [OCMockObject mockForClass:[FBSession class]];
[[mockSession expect] openWithBehavior:FBSessionLoginBehaviorWithNoFallbackToWebView completionHandler:nil];
[tester tapViewWithAccessibilityLabel:@"登録・ログイン"];
}
@end
参考
- categoryを使う方法 http://twobitlabs.com/2011/02/mocking-singletons-with-ocmock/
- method_exchangeImplementationsを使う方法 http://www.levelofindirection.com/journal/2013/7/11/injecting-singletons-in-objective-c-unit-tests.html
- 既存クラスのカスタマイズ方法について(公式) https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
- categoryでmethodが重複したことによるwarningを消す方法 http://stackoverflow.com/a/9622779/2387436