OHHTTPStubs
is a library designed to stub your network requests very easily. It can help you:
- test your apps with fake network data (stubbed from file) and simulate slow networks, to check your application behavior in bad network conditions
- write unit tests that use fake network data from your fixtures.
It works with NSURLConnection
, NSURLSession
, AFNetworking
, Alamofire
or any networking framework that use Cocoa's URL Loading System.
OHHTTPStubs
headers are fully documented using Appledoc-like / Headerdoc-like comments in the header files. You can also read the online documentation here.
In Objective-C
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
return [request.URL.host isEqualToString:@"mywebservice.com"];
} withStubResponse:^OHHTTPStubsResponse*(NSURLRequest *request) {
// Stub it with our "wsresponse.json" stub file (which is in same bundle as self)
NSString* fixture = OHPathForFile(@"wsresponse.json", self.class);
return [OHHTTPStubsResponse responseWithFileAtPath:fixture
statusCode:200 headers:@{@"Content-Type":@"application/json"}];
}];
In Swift
This example is using the Swift helpers found in OHHTTPStubsSwift.swift
provided by the OHHTTPStubs/Swift
subspec.
stub(isHost("mywebservice.com")) { _ in
// Stub it with our "wsresponse.json" stub file (which is in same bundle as self)
let stubPath = OHPathForFile("wsresponse.json", type(of: self))
return fixture(filePath: stubPath!, headers: ["Content-Type":"application/json"])
}
Note: if you're using OHHTTPStubs
's Swiftier API (OHHTTPStubsSwift.swift
and the Swift
subspec), you can also compose the matcher functions like this: stub(isScheme("http") && isHost("myhost")) { … }
- For a lot more examples, see the dedicated "Usage Examples" wiki page.
- The wiki also contain some articles that can help you get started with (and troubleshoot if needed)
OHHTTPStubs
.
Instead of writing the content of the stubs you want to use manually, you can use tools like SWHttpTrafficRecorder to record network requests into files. This way you can later use those files as stub responses.
This tool can record all three formats that are supported by OHHTTPStubs
(the HTTPMessage
format, the simple response boby/content file, and the Mocktail
format).
(There are also other ways to perform a similar task, including using curl -is <url> >foo.response
to generate files compatible with the HTTPMessage
format, or using other network recording libraries similar to SWHttpTrafficRecorder
).
OHHTTPStubs
is compatible with iOS5+, OS X 10.7+, tvOS.OHHTTPStubs
also works withNSURLSession
as well as any network library wrapping them.OHHTTPStubs
is fully compatible with Swift 2.2, 2.3 and 3.0.
Nullability annotations have also been added to the ObjC API to allow a cleaner API when used from Swift even if you don't use the dedicated Swift API wrapper provided by OHHTTPStubsSwift.swift
.
Note: When building with Swift 2.2, you will have some
extraneous '_' in parameter
warnings. Those are normal: it's because the code is already ready for the transition to Swift 3 — which requires those_
in parameters while Swift 2.2 didn't.
You can safely ignore those warnings in Swift 2.2. See SE-0046 for more info.
Using CocoaPods is the recommended way.
Simply add pod 'OHHTTPStubs'
to your Podfile
. If you intend to use it from Swift, you should add OHHTTPStubs/Swift
to your Podfile
as well.
pod 'OHHTTPStubs' # Default subspecs, including support for NSURLSession & JSON etc
pod 'OHHTTPStubs/Swift' # Adds the Swiftier API wrapper too
OHHTTPStubs
is split into subspecs so that when using Cocoapods, you can get only what you need, no more, no less.
- The default subspec includes
NSURLSession
,JSON
, andOHPathHelpers
- The
Swift
subspec adds the Swiftier API (but doesn't includeNSURLSession
&JSON
by itself) HTTPMessage
andMocktail
are opt-in subspecs: list them explicitly if you need themOHPathHelpers
doesn't depend onCore
and can be used independently ofOHHTTPStubs
altogether
List of all the subspecs & their dependencies
Here's a list of which subspecs are included for each of the different lines you could use in your Podfile
:
Subspec | Core | NSURLSession | JSON | Swift | OHPathHelpers | HTTPMessage | Mocktail |
---|---|---|---|---|---|---|---|
pod 'OHHTTPStubs' |
✅ | ✅ | ✅ | ✅ | |||
pod 'OHHTTPStubs/Default' |
✅ | ✅ | ✅ | ✅ | |||
pod 'OHHTTPStubs/Swift' |
✅ | ✅ | |||||
pod 'OHHTTPStubs/Core' |
✅ | ||||||
pod 'OHHTTPStubs/NSURLSession' |
✅ | ✅ | |||||
pod 'OHHTTPStubs/JSON' |
✅ | ✅ | |||||
pod 'OHHTTPStubs/OHPathHelpers' |
✅ | ||||||
pod 'OHHTTPStubs/HTTPMessage' |
✅ | ✅ | |||||
pod 'OHHTTPStubs/Mocktail' |
✅ | ✅ |
OHHTTPStubs
is also be compatible with Carthage. Just add it to your Cartfile
.
Note: The OHHTTPStubs.framework
built with Carthage will include all features of OHHTTPStubs
turned on (in other words, all subspecs of the pod), including NSURLSession
and JSON
support, OHPathHelpers
, HTTPMessage
and Mocktail
support, and the Swiftier API.
Be warned that I don't personally use Carthage, so I won't be able to guarantee much help/support for it.
OHHTTPStubs
supports Swift 2.2 (Xcode 7), and both Swift 2.3 and Swift 3.0 (Xcode 8) 🎉
Here are some details about the correct setup you need depending on how you integrated OHHTTPStubs
into your project.
CocoaPods
If you use CocoaPods version 1.1.0.beta.1
or later, then CocoaPods will compile OHHTTPStubs
with the right Swift Version matching the one you use for your project automatically.
For more info, see CocoaPods/CocoaPods#5540 and CocoaPods/CocoaPods#5760.
Carthage
The project is currently set up with SWIFT_VERSION=2.3
on master
.
This means that the framework on master
will build using Swift 2.2 on Xcode 7 and Swift 2.3 on Xcode 8.
If you want Carthage to build the framework with Swift 3.0, you can use the swift-3.0
branch, whose only difference with master
is that the project's Build Settings set SWIFT_VERSION=3.0
instead of 2.3
.
Note: Later, probably a few weeks after the Xcode 8 official release, we plan to merge the swift-3.0
branch into master
and create a compatibility branch swift-2.3
for Carthage users who have not migrated their Swift code yet. We'll try to keep the branch up-to-date with master as best we can.
Hopefully, Carthage will address this in a future release. See the related issue Carthage/Carthage#1445.
OHHTTPStubs
is ideal to write unit tests that normally would perform network requests. But if you use it in your unit tests, don't forget to:
- remove any stubs you installed after each test — to avoid those stubs to still be installed when executing the next Test Case — by calling
[OHHTTPStubs removeAllStubs]
in yourtearDown
method. see this wiki page for more info - be sure to wait until the request has received its response before doing your assertions and letting the test case finish (like for any asynchronous test). see this wiki page for more info
OHHTTPStubs
is automatically loaded and installed (at the time the library is loaded in memory), both for:
- requests made using
NSURLConnection
or[NSURLSession sharedSession]
— thanks to this code - requests made using a
NSURLSession
that was created via[NSURLSession sessionWithConfiguration:…]
and using either[NSURLSessionConfiguration defaultSessionConfiguration]
or[NSURLSessionConfiguration ephemeralSessionConfiguration]
configuration — thanks to method swizzling done here in the code.
If you need to disable (and re-enable) OHHTTPStubs
— globally or per NSURLSession
— you can use [OHHTTPStubs setEnabled:]
/ [OHHTTPStubs setEnabled:forSessionConfiguration:]
.
OHHTTPStubs
can't work on background sessions (sessions created using[NSURLSessionConfiguration backgroundSessionConfiguration]
) because background sessions don't allow the use of customNSURLProtocols
and are handled by the iOS Operating System itself.OHHTTPStubs
don't simulate data upload. TheNSURLProtocolClient
@protocol
does not provide a way to signal the delegate that data has been sent (only that some has been loaded), so any data in theHTTPBody
orHTTPBodyStream
of anNSURLRequest
, or data provided to-[NSURLSession uploadTaskWithRequest:fromData:];
will be ignored, and more importantly, the-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
delegate method will never be called when you stub the request usingOHHTTPStubs
.
As far as I know, there's nothing we can do about those two limitations. Please let me know if you know a solution that would make that possible anyway.
OHHTTPStubs
can be used on apps submitted on the App Store. It does not use any private API and nothing prevents you from shipping it.
But you generally only use stubs during the development phase and want to remove your stubs when submitting to the App Store. So be careful to only include OHHTTPStubs
when needed (only in your test targets, or only inside #if DEBUG
sections, or by using per-Build-Configuration pods) to avoid forgetting to remove it when the time comes that you release for the App Store and you want your requests to hit the real network!
This project and library has been created by Olivier Halligon (@aligatr on Twitter) and is under the MIT License.
It has been inspired by this article from InfiniteLoop.dk.
I would also like to thank Kevin Harwood (@kcharwood) for migrating the code to NSInputStream
, Jinlian Wang (@JinlianWang) for adding Mocktail support, and everyone else who contributed to this project on GitHub somehow.
If you want to support the development of this library, feel free to . Thanks to all contributors so far!