OHHTTPStubs not mocking requests if the iOS Application has it's own requests?
If the App does any Alamofire request before the tests run, OHHTTPStubs will not mock any requests in unit tests
OHHTTPStubs 4.3.0 with swift support
Alamofire 2.0.2
Test File - works as expected
stub(isHost("httpbin.org")) { _ in
let stubData = "Hello World!".dataUsingEncoding(NSUTF8StringEncoding)
return OHHTTPStubsResponse(data: stubData!, statusCode:200, headers:nil)
}
print("@@Start")
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.responseString() { request, response, data in
print(data)
}
But once you add the following to AppDelegate.swift, it no longer works and instead makes an actual HTTP request to the service
Alamofire.request(.GET, "http://httpbin.org/get")
.responseString() { request, response, data in
print(data)
}
Original question left for posterity
Update: I tried again in a clean project and it worked as expected so there must be something else going on.
In the latest upgrade to swift 2.0, OHHTTPStubs has not been stubbing the requests, and they're instead being passed through and called live.
I set up a short example in a unit test, but it's still passing through. What am I missing?
import Foundation
import Quick
import Nimble
import Alamofire
import OHHTTPStubs
class RequestsSpec: QuickSpec {
var data:Result<String>? = nil
override func spec() {
describe("the request") {
it("needs to make a request") {
stub(isHost("httpbin.org")) { _ in
let stubData = "Hello World!".dataUsingEncoding(NSUTF8StringEncoding)
return OHHTTPStubsResponse(data: stubData!, statusCode:200, headers:nil)
}
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.responseString() { request, response, data in
print(request)
print(response)
print(data)
print(data.value)
self.data = data
}
expect(self.data).toEventuallyNot(beNil(), timeout: 3)
}
}
}
I get
Optional(<NSMutableURLRequest: 0x7f91598e22e0> { URL: http://httpbin.org/get?foo=bar })
Optional(<NSHTTPURLResponse: 0x7f915da8c220> { URL: http://httpbin.org/get?foo=bar } { status code: 200, headers {
"Access-Control-Allow-Credentials" = true;
"Access-Control-Allow-Origin" = "*";
Connection = "keep-alive";
"Content-Length" = 364;
"Content-Type" = "application/json";
Date = "Thu, 01 Oct 2015 04:19:42 GMT";
Server = nginx;
} })
Optional("{\n \"args\": {\n \"foo\": \"bar\"\n }, \n \"headers\": {\n \"Accept\": \"*/*\", \n \"Accept-Encoding\": \"gzip;q=1.0,compress;q=0.5\", \n \"Accept-Language\": \"en-US;q=1.0\", \n \"Host\": \"httpbin.org\", \n \"User-Agent\": \"ios-consumer-app/com.dante.ouli2 (28; OS Version 9.0 (Build 13A340))\"\n }, \n \"url\": \"http://httpbin.org/get?foo=bar\"\n}\n")
Instead of Hello World!
I tried making the request with NSURLSession and OHHTTPStubs worked correctly. Looks like there's something wrong with the OHHTTPStubs/Alamofire interaction?
let url = NSURL(string: "http://httpbin.org/get")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
print(NSString(data: data!, encoding: NSUTF8StringEncoding))
self.data2 = data
}
Opened a ticket with the OHHTTPStubs. It's an edge case between Alamofire and OHHTTPStubs
https://github.com/AliSoftware/OHHTTPStubs/issues/126 Resolution is in the last two posts at the bottom
Some ideas to fix your edge case:
- Switch to non-hosted tests, so that your App doesn't get launched before your test bundle is loaded
- Keep hosted tests, but add OHHTTPStubs to your app bundle instead of your test bundle, so that it's loaded as soon as the app is launched when running your tests
- Hack your AppDelegate code somehow, so that when launched from the tests, it doesn't make any call to Alamofire.request, and that the first request made by Alamofire in the app or in the test (thus triggering its call to Manager.sharedInstance that creates its internal NSURLSessionConfiguration) is only done after the test bundle has been loaded and injected into your app bundle.
And what I ultimately did
I've made it so Alamofire requests aren't made during startup