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

后端 未结 2 1672
天涯浪人
天涯浪人 2021-01-14 03:28

I\'ve got an app where I push a UIAlertController with several custom UIAlertActions. Each UIAlertAction performs unique tasks in the

相关标签:
2条回答
  • 2021-01-14 04:18

    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];
    }
    
    0 讨论(0)
  • 2021-01-14 04:21

    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)

    0 讨论(0)
提交回复
热议问题