Mock NSHTTPURLRequest and NSHTTPURLResponse in iOS

2019-06-26 06:18发布

I'm developing a framework in iOS which makes HTTP calls to server.I wanted to write unit test to test the API's.I wanted to mock the server calls,without actually making real server call.Can anyone help me with sample unit test which makes mocked server calls.How to do we set expectations and return the hand constructed url response.?I'm using XCTest framework for unit test and OCMock for mocking objects.

2条回答
做个烂人
2楼-- · 2019-06-26 06:45

Here is how you might mock 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];

EDIT

To add clarification, here's what's happening. In this example our real code is calling [NSURLConnection sendAsynchronousRequest: queue: completionHandler:] There are three arguments passed to this method, plus the additional _cmd and self that is passed to all Objective-C method calls. Thus when we examine our NSInvocation the argument at index 4 is our completion handler. Since we are simulating the response from the server, we want to call this handler with fake data that represents the case we are testing.

The signature for the method call getArgumentAtIndexAsObject is in a header file included with OCMock, but is not included by default in the framework. I believe it is called NSInvocation+OCMAdditions.h. It makes fetching the invocation arguments easier by returning an id.

查看更多
做个烂人
3楼-- · 2019-06-26 06:50

Use OHTTPStubs, https://github.com/AliSoftware/OHHTTPStubs.

Here's a practical example of mocking the response to a specific GET request and returning JSON data.

[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" }];
}];
查看更多
登录 后发表回答