Specifying Content Type in rspec
Asked Answered
B

9

26

I'm trying to build an rspec test that sends JSON (or XML) via POST. However, I can't seem to actually get it working:

    json = {.... data ....}.to_json
    post '/model1.json',json,{'CONTENT_TYPE'=>'application/json'}

and this

    json = {.... data ....}.to_json
    post '/model1.json',json,{'Content-Type'=>'application/json'}

any ideas? THANKS!

Bachelorism answered 27/10, 2010 at 19:9 Comment(1)
Usually you POST to an action in a controller. Why are you posting to a file?Paraselene
S
20

In Rails 3, you can skip the header and @request.env stuff and just add a format parameter to your post call, e.g.:

post :create, format: :json, param: 'Value of Param'
Sievert answered 14/9, 2012 at 19:57 Comment(3)
Does using format: :json set request.accept and request.content_type to "application/json"?Theophrastus
This issue on rspec-rails implies that format: :json is the same as request.accept = "application/json".Theophrastus
It looks like in later versions of rails/rspec, format: :json got changed to as: :jsonFrias
S
18

There's a way to do this described in this thread -- it's a hack, but it seems to work:

@request.env["HTTP_ACCEPT"] = "application/json"
json = { ... data ... }.to_json
post :create, :some_param => json
Sicken answered 28/10, 2010 at 3:19 Comment(3)
This works with Rspec 2 and rails 3. (and was extremely difficult to find) Actually, I had to not use .to_json on the thing to get it to behave correctly. Otherwise, everything else worked fine.Hickerson
Thank you. I had a hard-time searching for solution to my failing tests before reading your answer.Andromada
I also found that request.accept = 'application/json' will work as well.Pachton
T
10

A lot of frustration and variations and that's what worked for me. Rails 3.2.12 Rspec 2.10

 @request.env["HTTP_ACCEPT"] = "application/json"
 @request.env["CONTENT_TYPE"] = "application/json"
 put :update, :id => 1, "email" => "[email protected]"
Trickle answered 26/3, 2013 at 1:45 Comment(1)
Thanks! I found out the one to work for me thanks to your answer: @request.env["CONTENT_TYPE"] = "application/json".Charged
G
5

First of all, you don't want to test the built-in conversion of json to hash. Same applies to xml.

You test controller with data as hashes, not bothering wether it's json, xml or from a html form.

But if you would like to do that as an exercise, this is a standalone ruby script to do play with :)

require 'json'
url = URI.parse('http://localhost:3030/mymodels.json')
request = Net::HTTP::Post.new(url.path)
request.content_type="application/json"
request.basic_auth('username', 'password')  #if used, else comment out

hash = {:mymodel => {:name => "Test Name 1", :description => "some data for testing description"}}
request.body = hash.to_json
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}
puts response

to switch to xml, use content_type="text/xml" and

request.body = "<?xml version='1.0' encoding='UTF-8'?><somedata><name>Test Name 1</name><description>Some data for testing</description></somedata>"
Garnet answered 10/11, 2010 at 12:24 Comment(0)
R
2

A slightly more elegant test is to use the header helper:

header "HTTP_ACCEPT", "application/json"
json = {.... data ....}.to_json
post '/model1.json', json

Now this does exactly the same thing as setting @env; it's just a bit prettier.

Robbins answered 29/6, 2012 at 12:8 Comment(2)
Where is this method defined? I get a NoMethodError when I try to call it.Primogenial
@PaulBrannan It's in rack/testRobbins
O
1

The best way that I have found to test these things is with request tests. Request tests go through the full param parsing and routing stages of Rails. So I can write a test like this:

request_params = {:id => 1, :some_attribute => "some value"}
headers = {'Accept' => 'application/json', 'Content-Type' => 'application/json'}
put "/url/path", request_params.to_json, headers
expect(response).to be_success
Offhand answered 1/8, 2014 at 19:54 Comment(0)
C
0

I think that you can specify the headers with headers param:

post '/model1.json', headers: {'Content-type': 'application/json'}

Following the Rspec documentation of how provide JSON data.

Chercherbourg answered 27/6, 2017 at 3:39 Comment(0)
K
0
@request.env["CONTENT_TYPE"] = "application/json"

OR pass in request

"CONTENT_TYPE" => "application/json"

Kingsize answered 31/10, 2017 at 11:3 Comment(0)
P
0
post '/model1.json', params: {.... data ....}, as: :json
Paraprofessional answered 16/5, 2024 at 23:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.