我有一个应用程序,我推送UIAlertController
多个自定义UIAlertAction
。每个UIAlertAction
在actionWithTitle:style:handler:
的处理程序块中执行唯一任务。
我需要验证的几个方法是在这些块中执行的。
如何执行handler
块以便我可以验证这些方法是否已执行?
答案 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];
}