OCMock and block testing, executing

前端 未结 3 2101
傲寒
傲寒 2021-02-05 22:44

Here\'s the method under test:

- (void)loginWithUser:(NSString *)userName andPass:(NSString *)pass {

    NSDictionary *userPassD = @{@\"user\":userName,
                


        
3条回答
  •  清酒与你
    2021-02-05 23:20

    Code I'm working with is heavily based on blocks, so I'm super familiar with your question.

    Just to rephrase problem a bit:

    - (ReturnObject *)methodThatWeWantToTest:(Foobar *)bar
    {    
           [self.somethingElse doSomethingAndCallBlock:^{
             // really want to test this code
           } secondBock:^{
            // even more code to test
           }];
    }
    

    To solve exactly the same problem you're bringing up here, we've created unit test helper class that has methods with identical signature to methods that call blocks that we need to test.

    For you code sample, it is a mock method that returns nothing, takes one id argument and two blocks.

    Below is example of the mock method you'd need and sample of the OCMock unit test that utilizes

    - (void)mockSuccessBlockWithOneArgumentTwoBlocks:(id)firstArgument
                                        successBlock:(void (^)(NSString *authtoken))successBlock
                                        failureBlock:(void (^)(NSString *errorMessage))failureBlock    
    {
        successBlock(@"mocked unit test auth token");
    }
    
    - (void)testLoginWithUserCallsSomethingInCredStoreOnLoginSuccess
    {
        LoginService *loginService = [[LoginService alloc] init];
    
        // init mocks we need for this test
        id credStoreMock = [OCMockObject niceMockForClass:[MyCredStore class]];
        id loginCtrlMock = [OCMockObject niceMockForClass:[MyLoginCtrl class]];
    
        // force login controller to call success block when called with loginWithUserPass
        // onObject:self - if mock method is in the same unit test, use self. if it is helper object, point to the helper object.
        [[[loginCtrlMock stub] andCall:@selector(mockSuccessBlockWithOneArgumentTwoBlocks:successBlock:failureBlock::) onObject:self] loginWithUserPass:OCMOCK_ANY withSuccess:OCMOCK_ANY failure:OCMOCK_ANY];
    
        // setup mocks
        loginService.credStore = credStoreMock;
        loginService.loginCtrl = loginCtrlMock;
    
        // expect/run/verify
        [[credStore expect] callSomethingFromSuccessBlock];
        [loginService loginWithUser:@"testUser" andPass:@"testPass"];
        [credStore verify];
    }
    

    Hope it helps! Let me know if you have any questions, we've got it working.

提交回复
热议问题