Paul Crono
Paul Crono

Reputation: 61

Testing method which uses AFNetworking with OCMock

I'm trying build some tests for my client class. I have simple method:

-(void)dataForLanguage:(NSString *)language withCompletionHandler:(void (^)(NSArray *, NSError *__autoreleasing *))block
{
    if(!language)
        language = @"en";

    [self GET:[NSString stringWithFormat:@"http://sample.com&lng=%@",language]
   parameters:nil
      success:^(NSURLSessionDataTask *task, id responseObject) {

          block(responseObject,NULL);

      }
      failure:^(NSURLSessionDataTask *task, NSError *error) {

          block(nil,&error);

      }];
}

I'm using OCMock for tests. I've already created few tests but without blocks and request stuff. For example I would like to create test to find out what happen when I will pass nil as a language parameter. How can i accomplish that ?

Then I would like to test that array is filled after success completion handler, but I really have no idea how to do that.

EDIT1: My class's interface looks like that:

@interface Client : AFHTTPSessionManager

EDIT2: I've tried test if array contains correct info:

-(void)test
{
    [[[partiallyMockApiClient stub] andDo:^(NSInvocation *invocation) {

        void (^successBlock)(NSURLSessionDataTask *task, id responseObject);
        [invocation getArgument: &successBlock atIndex: 4];
        successBlock(nil,[NSArray arrayWithObject:@"example"]);

    }] GET:OCMOCK_ANY parameters:OCMOCK_ANY success:OCMOCK_ANY failure:OCMOCK_ANY];

    [[[partiallyMockApiClient expect] andDo:^(NSInvocation *invocation) {

        void (^successBlock)(NSArray *dataInfo, NSError **error);
        [invocation getArgument: &successBlock atIndex: 3];
        successBlock([NSArray arrayWithObject:@"example"],NULL);

    }] dataForLanguage:nil withCompletionHandler:OCMOCK_ANY];

    [partiallyMockApiClient verify];
}

But it doesn't work. What am I doing wrong ?

EDIT3:

OK, first test according to your tips looks OK:

-(void)testApiClientReturnCorrentData
{
[[[partiallyMockApiClient expect] andDo:^(NSInvocation *invocation) {

    void (^successBlock)(NSURLSessionDataTask *task, id responseObject);
    [invocation getArgument: &successBlock atIndex: 4];
    successBlock(nil,[NSArray arrayWithObject:@"data"]);

}] GET:OCMOCK_ANY parameters:OCMOCK_ANY success:OCMOCK_ANY failure:OCMOCK_ANY];

[partiallyMockApiClient dataForLanguage:nil withCompletionHandler:^(NSArray *dataInfo, NSError *__autoreleasing *error) {
        XCTAssertTrue([dataInfo[0] isEqualToString:@"data"]);
    }];

}

Now i need to test that string URL is correct (contains english language) with nil parameter (language), I thought that will be ok:

-(void)testA
{
    [[partiallyMockApiClient expect] GET:@"http://sample.com/en/data.json"
                              parameters:OCMOCK_ANY
                                 success:OCMOCK_ANY
                                 failure:OCMOCK_ANY];
    [partiallyMockApiClient placesForLanguage:nil withCompletionHandler:OCMOCK_ANY];
    [partiallyMockApiClient verify];
}

but it doesn't, what's wrong ?

SOLUTION: Ok, i figured out what i was doing wrong, It should looks like that:

-(void)testA
{
    [[partiallyMockApiClient expect] GET:@"http://sample.com/en/data.json"
                              parameters:OCMOCK_ANY
                                 success:OCMOCK_ANY
                                 failure:OCMOCK_ANY];
    [partiallyMockApiClient placesForLanguage:nil withCompletionHandler:nil];
    [partiallyMockApiClient verify];
}

Thank You for your consideration.

Upvotes: 0

Views: 1251

Answers (1)

mspensieri
mspensieri

Reputation: 3521

Since you're overriding AFHTTPSessionManager, you can't really pass in a mocked networking object. You can, however, partially mock the object you are testing:

Client* myClient = [[Client alloc] init];
id partiallyMockedClient = [OCMockObject partialMockForObject:myClient];

Then, you can set up expectation on your partially mocked object:

[[partiallyMockedClient expect] GET:OCMOCK_ANY parameters:OCMOCK_ANY success:OCMOCK_ANY failure:OCMOCK_ANY];

To be able to call the success and failure blocks, use the OCMock andDo: method. Here's how you would call the success block:

[[[partiallyMockedClient expect] andDo:^(NSInvocation *) {
    void (^successBlock)(NSURLSessionDataTask *task, id responseObject);
    [invocation getArgument: &successBlock atIndex: 4];
    successBlock( /*  Some array of results   */);
}] GET:OCMOCK_ANY parameters:OCMOCK_ANY success:OCMOCK_ANY failure:OCMOCK_ANY];

EDIT

You then need to invoke the method you want to test, not just expect it:

[partiallyMockedClient dataForLanguage:@"someLanguage" 
                 withCompletionHandler:^(NSArray * array, NSError* error){
                     XCTAssertTrue([array[0] isEqualToString:@"example"]);
                 }];

Upvotes: 2

Related Questions