objective-c - 如何测试发出 HTTP 请求的类并在 Obj-C 中解析响应数据?

标签 objective-c unit-testing mocking

我有一个类需要向服务器发出 HTTP 请求以获取一些信息。例如:

- (NSUInteger)newsCount {
    NSHTTPURLResponse *response;
    NSError *error;
    NSURLRequest *request = ISKBuildRequestWithURL(ISKDesktopURL, ISKGet, cookie, nil, nil);
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    if (!data) {
        NSLog(@"The user's(%@) news count could not be obtained:%@", username, [error description]);
        return 0;
    }
    NSString *regExp = @"Usted tiene ([0-9]*) noticias? no leídas?";
    NSString *stringData = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    NSArray *match = [stringData captureComponentsMatchedByRegex:regExp];
    [stringData release];
    if ([match count] < 2)
        return 0;
    return [[match objectAtIndex:1] intValue];
}

问题是我正在对 hole 框架进行单元测试(使用 OCUnit),但问题是我需要模拟/伪造 NSURLConnection 正在响应的内容,以便测试不同的场景,因为我无法中继服务器来测试我的框架。

所以问题是最好的方法是什么?

最佳答案

测试调用类方法的方法总是很棘手,例如 NSURLConnection sendSynchronousRequest

这里有几个选项:

a) 使用 Matt Gallagher's invokeSupersequent macro拦截调用。您的单元测试将包含如下代码:

@implementation NSURLConneciton (UnitTests)

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error {
    if (someFlagYourTestUsesToInterceptTheCall) {        
        // return test NSData instance      
    }   
    return invokeSupersequent(request, &response, &error);
}

@end

然后您设置someFlagYourTestUsesToInterceptTheCall 以强制它拦截调用并返回您的测试数据。

b) 另一种方法是将该调用移动到被测类中它自己的方法中:

-(NSData *)retrieveNewsCount:(NSURLRequest *)request {
    NSHTTPURLResponse *response;
    NSError *error;
    return [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
}

然后使用 OCMock 在您的测试用例中拦截该调用:

-(void)testNewsCount {
    // instantiate your class
    id myObject = ...;
    id mock = [OCMockObject partialMockForObject:myObject];
    [[[mock stub] andCall:@selector(mockNewsCount:) onObject:self] retrieveNewsCount:[OCMArg any]];
    NSUInteger count = [myObject newsCount];
    // validate response
    ...
}

// in the same test class:
-(NSData *)mockNewsCount:(NSURLRequest *)request {
    // return your mock data
    return mockData;
}

在这种情况下,OCMock 的 stub:andCall:onObject:someMethod 仅拦截对对象方法的调用,以便在测试时注入(inject)一些测试数据。

关于objective-c - 如何测试发出 HTTP 请求的类并在 Obj-C 中解析响应数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2488492/

相关文章:

c - 如何在 C/Objective-C 中获取数组的大小?

javascript - 在 sails.js 中模拟/ stub 全局变量

python - 让一个测试方法返回多个测试结果

testing - 带参数的 Groovy 模拟方法

javascript - 使用 jest/enzyme 模拟模块功能

c# - 用于 Unity 的 Objective C iOS 插件

ios - 日期和月份名称的 NSDateFormatter

ios - 如何每 x 秒刷新 UITableView 的一个随机 UITableViewCell x 次。 Objective-C

c++ - 在测试之间清除 Boost Test Fixture 对象

c# - 无法将带 [] 的索引应用于类型 'CaSTLe.Proxies.RangeProxy' 的表达式