Stub your network requests easily! Test your apps with fake network data and custom response time, response code and headers!
OHHTTPStubsis a library designed to stub your network requests very easily. It can help you:
It works with
NSURLConnection,
NSURLSession,
AFNetworking,
Alamofireor any networking framework that use Cocoa's URL Loading System.
OHHTTPStubsheaders are fully documented using Appledoc-like / Headerdoc-like comments in the header files. You can also read the online documentation here.
[HTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
return [request.URL.host isEqualToString:@"mywebservice.com"];
} withStubResponse:^HTTPStubsResponse*(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 [HTTPStubsResponse responseWithFileAtPath:fixture
statusCode:200 headers:@{@"Content-Type":@"application/json"}];
}];
This example is using the Swift helpers found in OHHTTPStubsSwift.swift
provided by the OHHTTPStubs/Swift
subspec or OHHTTPStubs
package.
stub(condition: 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 or OHTTPStubsSwift
package), you can also compose the matcher functions like this: stub(isScheme("http") && isHost("myhost")) { … }
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
HTTPMessageformat, the simple response boby/content file, and the
Mocktailformat).
(There are also other ways to perform a similar task, including using
curl -is >foo.responseto generate files compatible with the
HTTPMessageformat, or using other network recording libraries similar to
SWHttpTrafficRecorder).
OHHTTPStubsis compatible with iOS5+, OS X 10.7+, tvOS.
OHHTTPStubsalso works with
NSURLSessionas well as any network library wrapping them.
OHHTTPStubsis fully compatible with Swift 3.x, 4.x and Swift 5.x.
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.
OH
prefix (OHHHTTPStubs
-> HTTPStubs
, OHHTTPStubsResponse
-> HTTPStubsResponse
, etc).OHPathHelpers
class was renamed HTTPStubsPathHelpers
.Using CocoaPods is the recommended way.
OHHTTPStubsfrom Objective-C only, add
pod 'OHHTTPStubs'to your
Podfile.
OHHTTPStubsfrom Swift, add
pod 'OHHTTPStubs/Swift'to your
Podfileinstead.
pod 'OHHTTPStubs/Swift' # includes the Default subspec, with support for NSURLSession & JSON, and the Swiftier API wrappers
OHHTTPStubsis split into subspecs so that when using Cocoapods, you can get only what you need, no more, no less.
NSURLSession,
JSON, and
OHPathHelpers
Swiftsubspec adds the Swiftier API to that default subspec
HTTPMessageand
Mocktailare opt-in subspecs: list them explicitly if you need them
OHPathHelpersdoesn't depend on
Coreand can be used independently of
OHHTTPStubsaltogether
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' |
✅ | ✅ |
OHHTTPStubsis compatible with Swift Package Manager, and provides 2 targets for consumption:
OHHTTPStubsand
OHHTTPStubsSwift.
OHHTTPStubsis equivalent to the
OHHTTPStubssubspec.
OHHTTPStubsSwiftis equivalent to the
OHHTTPStubs/Swiftsubspec.
Note: We currently do not have support for the HTTPMessage or Mocktail subspecs in Swift Package Manager. If you are interested in these, please open an issue to explain your needs.
OHHTTPStubsis also compatible with Carthage. Just add it to your
Cartfile.
Note: The
OHHTTPStubs.frameworkbuilt with Carthage will include all features of
OHHTTPStubsturned on (in other words, all subspecs of the pod), including
NSURLSessionand
JSONsupport,
OHPathHelpers,
HTTPMessageand
Mocktailsupport, and the Swiftier API.
OHHTTPStubssupports Swift 3.0 (Xcode 8+), Swift 3.1 (Xcode 8.3+), Swift 3.2 (Xcode 9.0+), Swift 4.0 (Xcode 9.0+), Swift 4.1 (Xcode 9.3+), Swift 4.2 (Xcode 10+), Swift 5.0 (Xcode 10.2), and Swift 5.1 (Xcode 11) however we are only testing Swift 4.x (using Xcode 9.1 and 10.1) and Swift 5.x (using Xcode 10.2 AND 11) in CI.
Here are some details about the correct setup you need depending on how you integrated
OHHTTPStubsinto your project.
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. You have nothing to do! 🎉
For more info, see CocoaPods/CocoaPods#5540 and CocoaPods/CocoaPods#5760.
The project is set up with SWIFT_VERSION=5.0
on master
.
This means that the framework on master
will build using:
If you want Carthage to build the framework with Swift 3.x you can:
OHHTTPStubs
(6.2.0) — whose master
branch uses 3.0
SWIFT_VERSION
build setting to 3.0
SWIFT_VERSION
to carthage via XCODE_XCCONFIG_FILE=<config file declaring swift_version> carthage build
OHHTTPStubsis ideal to write unit tests that normally would perform network requests. But if you use it in your unit tests, don't forget to:
[HTTPStubs removeAllStubs]in your
tearDownmethod. see this wiki page for more info
OHHTTPStubsis automatically loaded and installed (at the time the library is loaded in memory), both for:
NSURLConnectionor
[NSURLSession sharedSession]— thanks to this code
NSURLSessionthat 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
[HTTPStubs setEnabled:]/
[HTTPStubs setEnabled:forSessionConfiguration:].
OHHTTPStubscan't work on background sessions (sessions created using
[NSURLSessionConfiguration backgroundSessionConfiguration]) because background sessions don't allow the use of custom
NSURLProtocolsand are handled by the iOS Operating System itself.
OHHTTPStubsdon't simulate data upload. The
NSURLProtocolClient
@protocoldoes not provide a way to signal the delegate that data has been sent (only that some has been loaded), so any data in the
HTTPBodyor
HTTPBodyStreamof an
NSURLRequest, 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 using
OHHTTPStubs.
OHTTPStubshas a known issue with redirects that we believe is an Apple bug. It has been discussed here and here. The actual result of this bug is that redirects with a zero second delay may nondeterministically end up with a null response.
As far as I know, there's nothing we can do about those three limitations. Please let me know if you know a solution that would make that possible anyway.
OHHTTPStubscan 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
OHHTTPStubswhen needed (only in your test targets, or only inside
#if DEBUGsections, 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:
NSInputStream
If you want to support the development of this library, feel free to . Thanks to all contributors so far!