webmock: Response body can't be a hash
When I stub a request and specify a hash for the response body, I get the following error:
WebMock::Response::InvalidBody:
must be one of: [Proc, IO, Pathname, String, Array]. 'Hash' given
Is there a particular reason why it can’t be a hash?
About this issue
- Original URL
- State: open
- Created 9 years ago
- Reactions: 37
- Comments: 16 (6 by maintainers)
Commits related to this issue
- Allows JSON to be passed if JSON Content-Type Doesn't support hashes in general Re: https://github.com/bblimke/webmock/issues/449 — committed to LDonoughe/webmock by deleted user 7 years ago
- Allows JSON to be passed if JSON Content-Type Doesn't support hashes in general Re: https://github.com/bblimke/webmock/issues/449 — committed to LDonoughe/webmock by deleted user 7 years ago
- Fix: Clarify exception message Why this PR? Right now, users might be confused as to why a hash cannot be accepted as a response body? See Issue #449 on Github as well as #427. This seems to have c... — committed to benkoshy/webmock by benkoshy 4 years ago
Would it not be best to use the headers content-type to determine whether to return JSON or XML? I am stubbing as so
but would prefer not to have to call JSON.parse(response_body) since that is not a step that is required in my code as JSON is implicitly declared. Maybe I am missing something though? FWIW, I am using Faraday to make the actual request.
@pboling
HTTP response body is never a hash (there is no Hash content type). Your ruby HTTP client most likely does the response body parsing for you and converts is to a Hash. In order for your http client to know that the response body is JSON, you need to indicate that by the Content-Type header.
Thank you all for your answers, specially @joshuaswilcox and @bblimke. I was having issues with a spec for hours which mixed
WebMock
response with another gem expecting a hash. It wasn’t until I ended up here that I was able to work through it. Had to use bothJSON.generate
andContent-Type
suggestions.I’m leaving my solution here:
I am not sure that makes sense. If a server is actually returning JSON as the body content, the code parsing can assume its a Hash content type, therefore calling JSON.parse(response) will fail if its already a Hash. So its seems to me that Webmock should be able to send that as the response body, especially when a content-type of ‘application/json’ is explicitly passed.
I don’t think that is a problem to require a content-type when passing certain types of body content, since that is generally a good practice across http requests. Could i make a pull request for this functionality?
Most people will forget about headers.
Thank you so much @bblimke @joshuaswilcox @dduqueti.
Assuming
response
is a hash and I’m writing a Rails app I can simplify @dduqueti’s answer a little more using.to_json
:Please have a look at https://github.com/bblimke/webmock/pull/427
If response body is declared as a hash, it’s not clear what should the hash be encoded to. JSON, XML, or perhaps url params? Therefore WebMock expects you to stringify hash to expected encoding. I.e {a: b}.to_json
I think part of what makes this particularly confusing is that if you pass an empty hash, it doesn’t throw an error.
In case there is response content type declared it could work. Webmock would have to raise an error is case body is declared as a hash and headers are not declared.