How can you test the contents of a UIAlertAction handler with OCMock

眉间皱痕 提交于 2019-12-07 14:05:07

问题


I've got an app where I push a UIAlertController with several custom UIAlertActions. Each UIAlertAction performs unique tasks in the handler block of actionWithTitle:style:handler:.

I have several methods that I need to verify are executed within these blocks.

How can I execute the handler block so that I can verify that these methods are executed?


回答1:


With a bit of clever casting, I've found a way to do this in 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])
    }

}

This allows you to call alert.tapButtonAtIndex(1) in your test and have the correct handler executed.

(I would only use this in my test target, btw)




回答2:


After some playing around I finally figure it out. Turns out that the handler block can be cast as a function pointer and the function pointer can be executed.

Like so

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

Here's an example of how it would be used.

-(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];
}


来源:https://stackoverflow.com/questions/36926827/how-can-you-test-the-contents-of-a-uialertaction-handler-with-ocmock

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!