views:

689

answers:

4

I'm looking to send raw post data (e.g. unparamaterized json) to one of my controllers for testing:

class LegacyOrderUpdateControllerTest < ActionController::TestCase
 test "sending json" do
   post :index, '{"foo":"bar", "bool":true}'
 end
end

but this gives me a NoMethodError: undefined method `symbolize_keys' for #<String:0x00000102cb6080>

What is the correct way to send raw post data in ActionController::TestCase?

Here is some controller code

def index
    post_data = request.body.read
    req = JSON.parse(post_data)

A: 

post :index, {:foo=> 'bar', :bool => 'true'}

Sohan
That's not raw JSON, that's the hashed interpretation of it.
tadman
A: 

The post method expects a hash of name-value pairs, so you'll need to do something like this:

post :index, :data => '{"foo":"bar", "bool":true}'

Then, in your controller, get the data to be parsed like this:

post_data = params[:data]
Alex Reisner
I've tried this, it needs to be completely raw though{"response":"error","errors":"can't parse request: 598: unexpected token at 'data=
brian
How are you parsing the JSON in your controller? Could you add some controller code to your question?
Alex Reisner
ok I will do that now
brian
I've added a modification to your controller code in my answer.
Alex Reisner
A: 

Maybe it's the way you're formatting your JSON, it might need to be escaped some how? Try doing this:

post :index, :data => {:foo => 'bar', :bool => true }.to_json

This will turn the hash into json, and hopefully that should work. If not... well then I'm all out of ideas =)

jonnii
+4  A: 

I ran across the same issue today and found a solution.

In your test_helper.rb define the following method inside of ActiveSupport::TestCase:

  def raw_post(action, params, body)
    @request.env['RAW_POST_DATA'] = body
    response = post(action, params)
    @request.env.delete('RAW_POST_DATA')
    response
  end

In your functional test, use it just like the post method but pass the raw post body as the third argument.

class LegacyOrderUpdateControllerTest < ActionController::TestCase
 test "sending json" do
   raw_post :index, {}, {"foo":"bar", "bool":true}.to_json
 end
end

I tested this on Rails 2.3.4 when reading the raw post body using

request.raw_post

instead of

request.body.read

If you look at the source code you'll see that raw_post just wraps request.body.read with a check for this RAW_POST_DATA in the request env hash.

bbrowning
You rock, thanks
brian