OCMock facebook的块模拟
问题描述:
我想嘲笑facebook登录块,但测试失败,该块没有被调用。请帮我解决问题。OCMock facebook的块模拟
//Test
-(void)testFacebookLogin
{
id mockManager = OCMClassMock([FBSDKLoginManager class]);
OCMStub([[mockManager alloc]init]).andReturn(mockManager);
FBSDKLoginManagerLoginResult *res = [[FBSDKLoginManagerLoginResult alloc]initWithToken:nil isCancelled:YES grantedPermissions:nil declinedPermissions:nil];
NSError* err = [NSError errorWithDomain:@"This is an error" code:NSURLErrorNotConnectedToInternet userInfo:nil];
[[mockManager stub]logInWithReadPermissions:OCMOCK_ANY fromViewController:OCMOCK_ANY handler:[OCMArg invokeBlockWithArgs:res,err,nil]];
__block BOOL invoke;
[LoginHelper facebookLoginWithLoginResult:^(BOOL success, NSError *error, id result) {
invoke = YES;
}];
XCTAssertTrue(invoke);
}
//LoginHelper.m
+(void)facebookLoginWithLoginResult:(LoginResult)loginResult
{
UIViewController* currentRootViewController = AppDelegateHelperSingleton.globalDelegate.window.rootViewController;
FBSDKLoginManager* loginManager = [[FBSDKLoginManager alloc]init];
loginManager.loginBehavior = FBSDKLoginBehaviorNative;
NSArray* permissions = @[@"email",@"public_profile",@"user_birthday"];
//facebook login with read permisssions
[loginManager logInWithReadPermissions:permissions fromViewController:currentRootViewController handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
{
loginResult(result, error);
}];
}
答
OCMStub([[mockManager alloc]init]).andReturn(mockManager);
这是行不通的。你所面临的问题是,你的产品代码具有它锁定了一个依赖性:
FBSDKLoginManager* loginManager = [[FBSDKLoginManager alloc]init];
为了让你的测试代码提供一个“测试双”(一些真实的东西矗立在),你需要一种注入方式。
依赖注入有多种方法。你可以使它成为一个初始化参数。你可以把它变成财产。如果你想FBSDKLoginManager是短暂的,你可以把它作为一个方法参数。
欲了解更多信息,请参阅Dependency Injection: Unlock Your Code, Make It Testable
乔恩像往常一样是对的。然而,使用OCMock时,有一种(相当脏的)黑客攻击,当你不控制类时,它可以作为最后的手段。只要依赖对象没有使用简单的init方法初始化,或者alloc/init可以更改为'new',那么就可以存储'new'方法或alloc/initWith ...方法来返回模拟。参见9.3节。在参考文档中。 –