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

Ios 如何使用OCMock测试UIAlertAction处理程序的内容,ios,ocmock,Ios,Ocmock,我有一个应用程序,我推送一个带有几个自定义UIAlertActions的UIAlertController。每个UIAlertAction在actionWithTitle:style:handler:的处理程序块中执行唯一的任务 我有几个方法需要验证是否在这些块中执行 如何执行处理程序块,以便验证是否执行了这些方法?经过一番尝试后,我终于找到了答案。事实证明,处理程序块可以转换为函数指针,并且可以执行函数指针 像这样 UIAlertAction *action = myAlertControll

我有一个应用程序,我推送一个带有几个自定义
UIAlertAction
s的
UIAlertController
。每个
UIAlertAction
actionWithTitle:style: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];
}

通过巧妙的施法,我在Swift(2.2)中找到了一种实现这一点的方法:

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


(顺便说一句,我只会在我的测试目标中使用这个)

知道Swift中正确的类型是什么吗?简单地强制转换到预期的函数类型,在运行时会给出一条
EXC\u BAD\u指令
。我希望我能将这个答案提高两次。对模拟警报操作处理程序有很大帮助。我知道苹果可以改变它的工作方式,我的测试也会失败,但我现在愿意接受。这在Swift 3.0.1中失败,出现了
致命错误:无法在不同大小的类型之间取消安全广播,有人知道如何修复吗?
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])
    }

}