Search code examples
swift2alamofireohhttpstubs

OHHTTPStubs not stubbing host?


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
            }
  • OHHTTPStubs 4.3.0 with swift support
  • Alamofire 2.0.2

Solution

  • 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