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:

http://stackoverflow.com/questions/978061/http-get-with-request-body

--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/