Karthik207
Karthik207

Reputation: 493

Mock NSHTTPURLRequest and NSHTTPURLResponse in iOS unit test

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.

Upvotes: 4

Views: 3581

Answers (2)

dB.
dB.

Reputation: 4770

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

Upvotes: 2

Ben Flynn
Ben Flynn

Reputation: 18932

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.

Upvotes: 2

Related Questions