functional testing API: GET versus POST?

Hi,

I'm unable to properly test GET calls for my JSON API in Rails 3.1, using ActionController::TestCase.

get :loan, ActiveSupport::JSON.encode(minimum_valid_json_params), :format => :json

...where minimum_valid_json_params has the form...

{:one_thing=>"something", :another_thing=>23, ... }

...gives me the following unsatisfying error in the test:

NoMethodError: undefined method `symbolize_keys' for #<String:0x6304db>

So, my first question is: What setup do I need to properly test a JSON GET request that passes parameters, as above?

Next, I'm concerned that if I succeed with TestCase's get method, I may run into a problem in my controller: is request.body available for a GET request like mine, or is it only for PUT/POST?

Thanks,

Grar

Hi,

I'm unable to properly test GET calls for my JSON API in Rails 3.1, using ActionController::TestCase.

get :loan, ActiveSupport::JSON.encode(minimum_valid_json_params), :format => :json

...where minimum_valid_json_params has the form...

{:one_thing=>"something", :another_thing=>23, ... }

...gives me the following unsatisfying error in the test:

NoMethodError: undefined method `symbolize_keys' for #<String:0x6304db>

So, my first question is: What setup do I need to properly test a JSON GET request that passes parameters, as above?

The get method is expecting its second argument to be a hash of parameter name / value pairs, while JSON.encode is returning a string. I'm not certain what you'll need to change, as I don't know what format your controller is expecting the parameters in.

Next, I'm concerned that if I succeed with TestCase's get method, I may run into a problem in my controller: is request.body available for a GET request like mine, or is it only for PUT/POST?

GET requests do not typically have request bodies - depending on your web server, the body may or may not make it all the way to Rails. More discussion here:

--Matt Jones

Matt,

Thanks.

Continued work on this problem has shifted the emphasis, but I'm still blocked and could use help.

I've changed the request from a GET to a POST, just to remove uncertainty around the availability of the request.body for processing in the controller.

I now have the following error from the controller...

    JSON::ParserError: unexpected token at 'loan_request=4000000'

...where the controller code line in question is...

    data = ActiveSupport::JSON.decode(request.body.read)

...and the ActionController::TestCase test initiation of the error was...

    request = 4_000_000     post :loan, {:loan_request=>request, :format => :json}

...finally the test log of the request is...

  Processing by Sec223fAcquisitionController#loan as JSON   Parameters: {"loan_request"=>"4000000"} Completed 500 Internal Server Error in 28ms

Can someone please offer thoughts, or, perhaps better, an example of the same kind of attempt, successfully made using either Rais TestCase or RSpec?

Thanks,

Grar

Hey,

Sorry to promote this again, but I'm stuck. Anybody?

Grar

Those of us who read this via normal email don't have prior context. Please recap (briefly) what problem you're trying to get help with.

Thanks, Dave

Dave,

Thanks for the consideration you show to this issue of mine, here is the recap...

I have the following error from my Rails 3.1 controller...

    JSON::ParserError: unexpected token at 'loan_request=4000000'

...where the controller code line in question is...

    data = ActiveSupport::JSON.decode(request.body.read)

...and the ActionController::TestCase test initiation of the error was...

    request = 4_000_000     post :loan, {:loan_request=>request, :format => :json}

...finally the test log of the request is...

  Processing by Sec223fAcquisitionController#loan as JSON   Parameters: {"loan_request"=>"4000000"} Completed 500 Internal Server Error in 28ms

What bugs me here is that I don't see the JSON format appear anywhere above. I understand why the parser would choke on 'loan_request=4000000', because it's not JSON.

Grar

Dave,

Thanks for the consideration you show to this issue of mine, here is the recap...

I have the following error from my Rails 3.1 controller...

JSON::ParserError: unexpected token at 'loan_request=4000000'

...where the controller code line in question is...

data = ActiveSupport::JSON.decode(request.body.read)

I can't say that I fully understand what you are doing here but that does not normally stop me trying to help. If you break here using ruby-debug and inspect request.body.read what do you see?

Colin

Exactly. You're telling it to parse the stuff as JSON, but you're not sending it JSON. Try JSON-encoding the request before you send it.

-Dave

Colin,

Here's some of the debug trace...

=> 14 data = ActiveSupport::JSON.decode(request.body.read)

(rdb:1) p request.body.read "loan=4000000"

So, this is consistent with the controller error..

    JSON::ParserError: unexpected token at 'loan_request=4000000'

My functional testing approach using...

    request = 4_000_000     post :loan, {:loan_request=>request, :format => :json}

...is not formulating the request as JSON?

So, what, from anyone who tests JSON API's using functional methods is the proper usage?

(I figure I'll soon have to move on to test with Cucumber, which seems to enjoy more examples around API testing...)

Grar

request = 4_000_000 post :loan, {:loan_request=>request, :format => :json}

...is not formulating the request as JSON?

Correct. This is exactly why you're getting:

(rdb:1) p request.body.read "loan=4000000"

I'm wondering though what happens to the "_request" part. Did you maybe transcribe by hand and drop it? I am not personally familiar with generating JSON from Ruby, but it seems to me that the hash above should generate something like "{ loan_request: 4000000 }". You could try making *that* string the value of loan_request.

Or maybe something's getting confused with the multiple usage of the term "request"? Try renaming loan_request to loan_amount and see what happens.

-Dave

   request = 4_000_000    post :loan, {:loan_request=>request, :format => :json}

...finally the test log of the request is...

Processing by Sec223fAcquisitionController#loan as JSON

The influence of the :format=>:json bit is ... ^^here^^. If you compare this to other requests, you'll probably see that they are "as HTML"

Parameters: {"loan_request"=>"4000000"} Completed 500 Internal Server Error in 28ms

What bugs me here is that I don't see the JSON format appear anywhere above. I understand why the parser would choke on 'loan_request=4000000', because it's not JSON.

Grar

the "as JSON" is that the response is desired in JSON format, not that the request parameters are in that format. You can see from the log output that the parameter is what you expect:   params[:loan_request] == 4000000

What does the rest of the loan action look like?

-Rob

Rob Biedenharn Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/ rab@GaslightSoftware.com http://GaslightSoftware.com/