Skip to main content
Sébastien Duperron
@liquidseb
Refactoring and implementing the
(near) future
OHHTTPStubs
CocoaHeads Paris
11 février 2016
Your
App
Stubs
🚫
How it works
Network
What it does
Intercept network requests:
• Fake network data using files or code
• Simulate slow network conditions
Where you can use it
• Unit tests / UI tests
• Slow network integration tests
• Features with yet to implement web services
Limitations
• Do not support Background sessions
• Cannot stub data upload
How to implement it
Content
Request
Objective-C
How to implement it
Content
Request
Swift
How to implement it
- (void)testFoo
{
NSURLRequest* request = ...
XCTestExpectation* responseArrived = [self expectationWithDescription:@"response of
async request has arrived"];
__block NSData* receivedData = nil;
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse* response, NSData* data,
NSError* error)
{
receivedData = data;
[responseArrived fulfill];
}
];
[self waitForExpectationsWithTimeout:timeout handler:^{
XCTAssertNotNil(receivedData, @"Received data should not be nil");
}];
}
UnitTest asynchronous example
How to implement it
Remove stubs in UnitTest tearDown
- (void)tearDown
{
[OHHTTPStubs removeAllStubs];
[super tearDown];
}
⚠ ⚠
Response API
• NSData
• Path
• JSON object
Successful request response
return [OHHTTPStubsResponse
responseWithFileAtPath:OHPathForFile(@"wsresponse.json",self.class)
statusCode:200
headers:@{@"Content-Type":@"application/json"}];
NSDictionary* obj = @{ @"key1": @"value1", @"key2": @[@"value2A", @"value2B"] };
return [OHHTTPStubsResponse responseWithJSONObject:obj statusCode:200 headers:nil];
NSData* stubData = [@"Hello World!" dataUsingEncoding:NSUTF8StringEncoding];
return [OHHTTPStubsResponse responseWithData:stubData statusCode:200 headers:nil];
Response API
Failed request
NSError* notConnectedError =
[NSError errorWithDomain:NSURLErrorDomain
code:kCFURLErrorNotConnectedToInternet
userInfo:nil];
return [OHHTTPStubsResponse responseWithError:notConnectedError];
NSError
Response API
• requestTime
• responseTime
Request / Response delay
OHHTTPStubsDownloadSpeed1KBPS
OHHTTPStubsDownloadSpeedSLOW
OHHTTPStubsDownloadSpeedGPRS
OHHTTPStubsDownloadSpeedEDGE
OHHTTPStubsDownloadSpeed3G
OHHTTPStubsDownloadSpeed3GPlus
OHHTTPStubsDownloadSpeedWifi
Special values
Response API
You can chain responseTime: method call
Request / Response delay
return [[OHHTTPStubsResponse responseWithData:[NSData data]
statusCode:400
headers:nil]
responseTime:OHHTTPStubsDownloadSpeed3G]
First example
Refactoring our network code
Our context
• Two network modules:
1 legacy with NSURLConnection
1 new with AFNetworking
• Server and App code with little or no
documentation
• No tests
Can’t we just rewrite the
old code and be done
with it ?
Of course.
But what about regressions?
But we cannot write tests on
the old network code?!
• new API is different (block callbacks vs delegation
to objects)
• network logic is mostly inside controllers
What we have
Controller
Request
Manual Object
Mapping
Legacy Network Module
NSURLConnection
How do we test this ?
What do we do in a test?
• Given a set of inputs
• When operating on this set
• Then check the outputs
How do we test this?
Controller
Request
Manual Object
Mapping
Legacy Network Module
NSURLConnection OHHTTPStubs
• check network
call
• return expected
JSON data
Check mappingTest call
How do we do this?
1.Gather existing requests with corresponding
responses
2.Use OHHTTPStubs to stub the requests
3.Implement tests on existing code
4.Refactor!
Controller
Before/After refactoring
Controller
Request
Manual Object
Mapping
Legacy Network Module
NSURLConnection
New Network Module
AFNetworking
Automatic
Object Mapping
Previous implementation New implementation
Requests
Factory
Second example
Stubbing yet-to-implement web services
Context
• All teams have different roadmaps (mostly)
• This means milestones (which are sometimes
deadlines)
Roadmap
iOS team
Server team
THE feature
Other important stuff
Webservice for
THE feature
Release
deadline
T
Apple
Review
How can we achieve this?
• Specify the web service entry point precisely
(parameters and output data)
• Stub the request using this specification
• Develop the feature (with its tests!)
How can we achieve this?
OHHTTPStubs
JSON
Files
NSURLConnection NSURLSession
What we have used
JSON configuration files
}Stubbed
request
}JSON
stub
https://github.com/AliSoftware/OHHTTPStubs
Sébastien Duperron - @liquidseb
Viadeo
Maintainer: Olivier Halligon (@aligatr)
Questions ?
OHHTTPStubs