使用AFNetworking和OCMock的测试方法

时间:2014-05-01 16:23:47

标签: ios objective-c unit-testing ocmock

我正在尝试为我的客户端类构建一些测试。我有简单的方法:

-(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);

      }];
}

我正在使用OCMock进行测试。我已经创建了一些测试但没有块和请求的东西。例如,我想创建测试以找出当我将nil作为语言参数传递时会发生什么。我怎么能做到这一点?

然后我想在成功完成处理程序之后测试该数组是否已填充,但我真的不知道该怎么做。

EDIT1: 我班级的界面如下:

@interface Client : AFHTTPSessionManager

EDIT2: 我已经尝试过测试数组是否包含正确的信息:

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

但它不起作用。我做错了什么?

EDIT3:

好的,首先根据你的提示进行测试看起来不错:

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

}

现在我需要用nil参数(语言)来测试字符串URL是否正确(包含英语),我认为这样就可以了:

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

但它没有,出了什么问题?

解: 好吧,我弄清楚我做错了什么,看起来应该是这样的:

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

感谢您的考虑。

1 个答案:

答案 0 :(得分:2)

由于您要覆盖AFHTTPSessionManager,因此您无法真正传递模拟的网络对象。但是,您可以部分模拟正在测试的对象:

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

然后,您可以对部分模拟的对象设置期望值:

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

为了能够调用成功和失败块,请使用OCMock andDo:方法。以下是您如何调用成功块:

[[[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];

修改

然后,您需要调用要测试的方法,而不仅仅是期望它:

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