Mockingjay icon indicating copy to clipboard operation
Mockingjay copied to clipboard

add Matcher Compare HTTPBody

Open hiroraba opened this issue 9 years ago • 4 comments

Hello. add Matcher Compare HTTPBody. for examplle, using when POST with json.

hiroraba avatar Jan 16 '16 08:01 hiroraba

Thanks for the pull request. I've never had this use case (since usually I deal with JSON etc and would use JSON comparisons instead). Is this common in your app? I'm wondering what content-types you are using.

kylef avatar Jan 20 '16 11:01 kylef

Note that this wouldn't work because of how NSURLProtocol is implemented: https://github.com/AliSoftware/OHHTTPStubs/wiki/Testing-for-the-request-body-in-your-stubs

marcelofabri avatar Sep 06 '16 01:09 marcelofabri

Indeed there is no access to httpBody. According to the documentation you should be able to het the httpBodyStream. But that also does not work. I tried that using:

    func httpbody(_ method: HTTPMethod, uri: String, body: String) -> (_ request: URLRequest) -> Bool {
        return { (request: URLRequest) in
            if let requestMethod = request.httpMethod {
                let httpBody = getStreamData(request.httpBodyStream)
                if requestMethod == method.description && httpBody == body {
                    return Mockingjay.uri(uri)(request)
                }
            }
            return false
        }
    }

    func getStreamData(_ inputStream: InputStream?) -> String? {
        let bufferSize = 1024
        var buffer = Array<UInt8>(repeating: 0, count: bufferSize)

        let bytesRead = inputStream?.read(&buffer, maxLength: bufferSize) ?? -1
        if bytesRead >= 0 {
            return NSString(bytes: &buffer, length: bytesRead, encoding: String.Encoding.utf8.rawValue) as String?
        }
        return nil
    }

How else can we check the posted data? Is implementing a workaround like marcelofabri mentioned the only solution?

evermeer avatar Nov 18 '16 10:11 evermeer

This workaround seems to be working for me. Since I only have 1 place where i set the httpBody for a request, I also saved the data as a property in the request like this:

            request.httpBody = data
            if isRunningUITests() {
                //Workaround fix so that we are able to get the httpBody in the mocked protocol
                URLProtocol.setProperty(data, forKey: "PersistantHttpBody", in: request)
            }

In the matcher or the builder you an then get that data using:

    let data = String(data: (URLProtocol.property(forKey: "PersistantHttpBody", in: request) as? Data) ?? Data(), encoding: .utf8)

This is generally the same solution as is in https://github.com/AliSoftware/OHHTTPStubs/wiki/Testing-for-the-request-body-in-your-stubs only the .httpBody property is not swizzeled so that we have to set the property ourselfes the moment we set the .httpBody

evermeer avatar Nov 18 '16 11:11 evermeer