如何使用OCMock测试UIAlertAction处理程序的内容

时间:2016-04-28 22:55:12

标签: ios ocmock

我有一个应用程序,我推送UIAlertController多个自定义UIAlertAction。每个UIAlertActionactionWithTitle:style:handler:的处理程序块中执行唯一任务。

我需要验证的几个方法是在这些块中执行的。

如何执行handler块以便我可以验证这些方法是否已执行?

2 个答案:

答案 0 :(得分:2)

通过一些巧妙的演员,我在Swift(2.2)中找到了一种方法:

extension UIAlertController {

    typealias AlertHandler = @convention(block) (UIAlertAction) -> Void

    func tapButtonAtIndex(index: Int) {
        let block = actions[index].valueForKey("handler")
        let handler = unsafeBitCast(block, AlertHandler.self)

        handler(actions[index])
    }

}

这允许您在测试中调用alert.tapButtonAtIndex(1)并执行正确的处理程序。

(我只会在我的测试目标中使用它,顺便说一下)

答案 1 :(得分:1)

经过一番游戏,我终于明白了。原来可以将handler块转换为函数指针,并且可以执行函数指针。

喜欢这样

UIAlertAction *action = myAlertController.actions[0];
void (^someBlock)(id obj) = [action valueForKey:@"handler"];
someBlock(action);

以下是如何使用它的示例。

-(void)test_verifyThatIfUserSelectsTheFirstActionOfMyAlertControllerSomeMethodIsCalled {

    //Setup expectations
    [[_partialMockViewController expect] someMethod];

    //When the UIAlertController is presented automatically simulate a "tap" of the first button
    [[_partialMockViewController stub] presentViewController:[OCMArg checkWithBlock:^BOOL(id obj) {

        XCTAssert([obj isKindOfClass:[UIAlertController class]]);

        UIAlertController *alert = (UIAlertController*)obj;

        //Get the first button
        UIAlertAction *action = alert.actions[0];

        //Cast the pointer of the handle block into a form that we can execute
        void (^someBlock)(id obj) = [action valueForKey:@"handler"];

        //Execute the code of the join button
        someBlock(action);
    }]
                                         animated:YES
                                       completion:nil];

   //Execute the method that displays the UIAlertController
   [_viewControllerUnderTest methodThatDisplaysAlertController];

   //Verify that |someMethod| was executed
   [_partialMockViewController verify];
}