在iOS单元测试中模拟NSHTTPURLRequest和NSHTTPURLResponse

时间:2013-12-18 06:10:36

标签: ios unit-testing ocmock xctest

我正在iOS中开发一个框架,它对服务器进行HTTP调用。我想编写单元测试来测试API。我想模拟服务器调用,而不是实际调用真正的服务器。任何人都可以帮我提供样本使模拟服务器调用的单元测试。如何设置期望并返回手工构建的url响应。我使用XCTest框架进行单元测试,使用OCMock进行模拟对象。

2 个答案:

答案 0 :(得分:2)

以下是模拟sendAsynchronousRequest的方法:

NSDictionary *serverResponse = @{ @"response" : [[NSHTTPURLResponse alloc] initWithURL:nil statusCode:200 HTTPVersion:nil headerFields:@{}],
                                  @"data" : [@"SOMEDATA" dataUsingEncoding:NSUTF8StringEncoding]
                                  };

id connectionMock = [OCMockObject mockForClass:NSURLConnection.class];
[[[connectionMock expect] andDo:^(NSInvocation *invocation) {
    void (^handler)(NSURLResponse*, NSData*, NSError*);
    handler = [invocation getArgumentAtIndexAsObject:4];
    handler(serverResponse[@"response"], serverResponse[@"data"], serverResponse[@"error"]);
}] sendAsynchronousRequest:OCMOCK_ANY queue:OCMOCK_ANY completionHandler:OCMOCK_ANY];

修改

为了补充说明,这是正在发生的事情。在此示例中,我们的实际代码是调用[NSURLConnection sendAsynchronousRequest: queue: completionHandler:]。此方法传递了三个参数,以及传递给所有Objective-C方法调用的其他_cmdself。因此,当我们检查我们的NSInvocation时,索引4处的参数是我们的完成处理程序。由于我们正在模拟来自服务器的响应,因此我们希望使用表示我们正在测试的案例的假数据来调用此处理程序。

方法调用getArgumentAtIndexAsObject的签名位于OCMock附带的头文件中,但默认情况下不包含在框架中。我相信它被称为NSInvocation+OCMAdditions.h。它通过返回id来轻松获取调用参数。

答案 1 :(得分:2)

使用OHTTPStubs,https://github.com/AliSoftware/OHHTTPStubs

这是一个模拟对特定GET请求的响应并返回JSON数据的实际示例。

[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
    return [request.URL.path isEqualToString:@"/api/widget"];
} withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
    id JSON = @{ @"id": @"1234", @"name" : @"gadget" };
    NSData *data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil];
    return [OHHTTPStubsResponse responseWithData:data statusCode:200 headers:@{ @"Content-Type": @"application/json" }];
}];