iosobjective-c-blockskiwi

Block is null when trying Kiwi stubWithBlock:


I'm trying to test that my App behaves correctly based on the success or failure of my API call.

when I break point the __block statements, the block is nil (EXC_BAD_ACCESS) When I call the userSuccess block at the bottom, it is also nil. I'm still trying to wrap my head fully around blocks. Thought I had it this time, but obviously not.

Any help greatly appreciated

    __block void (^userSuccess)(NSDictionary *data);
    __block void (^userFailure)(NSError *error);
    __block void (^authSuccess)(NSDictionary *authData);
    __block void (^authFailure)(NSError *authError);

    beforeAll(^{

        [testController stub:@selector(userManager) andReturn:[KWMock nullMockForClass:[CLASS class]]];

        [testController stub:@selector(authManager) andReturn:[KWMock nullMockForClass:[CLASS class]]];

        [testController.userManager stub:@selector(createWithData:success:failure:) withBlock:^id(NSArray *params) {

            userSuccess = [params objectAtIndex:1];
            userFailure = [params objectAtIndex:2];
            return nil;
        }];

        [testController.authManager stub:@selector(loginWithEmail:password:disableLaunch:success:failure:) withBlock:^id(NSArray *params) {

            authSuccess = [params objectAtIndex:3];
            authFailure = [params objectAtIndex:4];
            return nil;
        }];
    });

    it(@"should attempt to hit auth after a successful user call", ^{

        [[testController.authManager should] receive:@selector(loginWithEmail:password:disableLaunch:success:failure:)];
        NSDictionary *responseData = @{};
        userSuccess(responseData);
    });

Solution

  • Some problems noticed:

    1. The "should receive" expectation set in your test overwrites the stubs you set in beforeAll()
    2. you should be using a beforeEach(), it gives you more control over the tests (although in this particular case with only one test, beforeEach and beforeAll behave the same)
    3. You are not triggering any execution of code, you are only setting expectancies.
    4. I have some more observations regarding the overwrite of getters for your controller, however that's a longer topic.

    Fixing #3 and #1 should resolve your problem, as the cause of the problem is the fact that the login method on the controller is not called, and even if called, the expectancy set in the test overwrites the one set in the beforeAll() call.