如何用OCMocktestingUIAlertAction处理程序的内容

我有一个应用程序,我推送一个UIAlertController与几个自定义的UIAlertAction 。 每个UIAlertActionUIAlertAction的处理程序块中执行独特的任务actionWithTitle:style:handler:

我有几个方法,我需要validation在这些块内执行。

我怎样才能执行handler块,以便我可以validation这些方法执行?

在玩了一段时间之后,我终于搞清楚了。 事实certificate, 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)中做到这一点的方法:

 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]) } } 

这使您可以在testing中调用alert.tapButtonAtIndex(1) ,并执行正确的处理程序。

(我只会用在我的testing目标,顺便说一句)