如何用OCMocktestingUIAlertAction处理程序的内容
我有一个应用程序,我推送一个UIAlertController
与几个自定义的UIAlertAction
。 每个UIAlertAction
在UIAlertAction
的处理程序块中执行独特的任务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目标,顺便说一句)