6

I'm trying to test the request body sent captured with OHHTTPStubs but it seems buggy returning because the request.httpBody is nil.

I found this info about this problem Testing for the request body in your stubs. But I'm pretty new in iOS development and don't know how to access to OHHTTPStubs_HTTPBody in Swift. How can I do this?

jscs
  • 63,694
  • 13
  • 151
  • 195
Addev
  • 31,819
  • 51
  • 183
  • 302

2 Answers2

11

I guess rough equivalent in Swift will be following:

import OHHTTPStubs.NSURLRequest_HTTPBodyTesting
...
stub(isMethodPOST() && testBody()) { _ in
  return OHHTTPStubsResponse(data: validLoginResponseData, statusCode:200, headers:nil)
}).name = "login"

public func testBody() -> OHHTTPStubsTestBlock {
  return { req in 
    let body = req.ohhttpStubs_HTTPBody()
    let bodyString = String.init(data: body, encoding: String.Encoding.utf8)

    return bodyString == "user=foo&password=bar"
  }
}

So, more precisely, you can access OHHTTPStubs_HTTPBody by calling ohhttpStubs_HTTPBody() method inside OHHTTPStubsTestBlock.

Anton Malmygin
  • 3,406
  • 2
  • 25
  • 31
  • 1
    Since Swift 3 there is a small difference as request is URLRequest and the extension of OHHTTPSubs has been written for NSURLRequest. That means you need to typecast your request object first: `let nsRequest = request as NSURLRequest` and then you can use `nsRequest.ohhttpStubs_HTTPBody()` – JanMensch Aug 17 '17 at 14:43
  • @JanBrinker FYI It seems they have made an update so you don't need to cast anymore. It is available on `URLRequest` as a property: `ohhttpStubs_httpBody` so you can just do `let body = req.ohhttpStubs_httpBody` – RcoderNY Feb 05 '23 at 21:59
1

What worked for me is the following:

func testYourStuff() {

    let semaphore = DispatchSemaphore(value: 0)

    stub(condition: isScheme(https)) { request in
        if request.url!.host == "blah.com" && request.url!.path == "/blah/stuff" {

            let data = Data(reading: request.httpBodyStream!)
            let dict = Support.dataToDict(with: data)

            // at this point of time you have your data to test
            // for example dictionary as I have
            XCTAssertTrue(...)

        } else {
            XCTFail()
        }

        // flag that we got inside of this block
        semaphore.signal()

        return OHHTTPStubsResponse(jsonObject: [:], statusCode:200, headers:nil)
    }

    // this code will be executed first,
    // but we still need to wait till our stub code will be completed
    CODE to make https request

    _ = semaphore.wait(timeout: DispatchTime.distantFuture)
}

// convert InputStream to Data
extension Data {

init(reading input: InputStream) {

    self.init()
    input.open()

    let bufferSize = 1024
    let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
    while input.hasBytesAvailable {
        let read = input.read(buffer, maxLength: bufferSize)
        self.append(buffer, count: read)
    }
    buffer.deallocate(capacity: bufferSize)

    input.close()
  }
}

Credits to this person for converting InputStrem to Data: Reading an InputStream into a Data object

Eugene
  • 19
  • 3