Rspec-rails: Request Specs Converting Non String Values to Strings

Created on 19 Sep 2012  路  14Comments  路  Source: rspec/rspec-rails

as a request spec both of these fails because they get converted into strings.

require 'spec_helper'

describe 'parameters' do
  before { post 'orders.json', order: {boolean: true, integer: 123} }
  it 'should have boolean value' do
    request.params['order']['boolean'].should == true
  end
  it 'should have integer value' do
    request.params['order']['integer'].should == 123
  end
end

as a controller spec boolean passes, integer fails.

require 'spec_helper'

describe OrdersController do
  before { post :create, order: {boolean: true, integer: 123} }
  it 'should have boolean value' do
    controller.params['order']['boolean'].should == true
  end
  it 'should have integer value' do
    controller.params['order']['integer'].should == 123
  end
end

This is with Rails 3.2.8 and RSpec 2.11.0

Most helpful comment

@jrochkind try as: :json

All 14 comments

You'll want to post this to the https://github.com/rails/rails/issues as the conversions happen in ActionDispatch::Integration::Runner for request specs and ActionController::TestCase::Behavior for controller specs.

This is actually by design: URL parameters will come into your application as strings. e.g., http://example.com/?foo=bar&baz=1 will be parsed into params as { :foo => "bar", :baz => "1" }. There's no information the application can use to correctly type values as anything but strings.

The specifics of request vs. controller specs are a bit more complicated if I remember correctly. I believe request specs have always exhibited this behavior; controller specs changed with this Rails commit: https://github.com/rails/rails/commit/7fd726d62e8483c5bdb39c7f5b9d267e6b7fbaa6

tldr: it's more realistic that the parameters come in as strings because that's what will happen in real HTTP requests.

The problem I'm finding is if I pass in a boolean or integer through the actual application I'll get the boolean or integer value and not as a string.

In the actual application, is the data coming across as URL-encoded form data .. or something like JSON (which has support for certain types, including numbers and booleans)?

It's coming in as JSON and not form data.

@alindeman @vizjerai you're welcome to continue this convo here, but this is a Rails issue, not RSpec, so we can't fix it here. I'd recommend opening a similar issue in the Rails project.

@dchelimsky, agreed. I think RSpec and Rails are operating correctly: I am just trying to be a bit helpful, though maybe there are better venues for that?

@vizjerai, JSON data can be typed, so that's why you're seeing things correctly in production. The request and controller specs you showed are submitting parameters via URL parameters/form data ... so there's a mismatch between your tests and reality. Rails is trying to be helpful by stringifying/paramifying as would happen in reality if the parameters were form data.

This is one way to submit JSON in a Rails integration test (a.k.a RSpec request spec):

post 'orders.json', JSON.dump(order: {boolean: true, integer: 123}),
                    "CONTENT_TYPE" => "application/json"

@alindeman, thanks that works great for the request specs. But I'm at a loss on how to get the controller specs to work correctly...

@alindeman, Nevermind, it works. I forgot I rolled back the version of rails I had that was before the change you mentioned to rails above.

post :create, order: {boolean: true, integer: 123}, format: :json

If anyone's struggling with this, as of rails 4.2, you can get it to work with:

    post :create, {order: {boolean: true, integer: 123}, :format => :json}

Shoutout to these folks

In Rails5, I seem to be having this problem again. Even with format: :json, all integers get turned into strings, which does _not_ match how Rails is actually delivering them to me in production (from a json-format post'd body).

Is there a regression in rails5?

@jrochkind try as: :json

Yep, that's what worked. Sorry I forgot to come back and update, I was knee deep in yak shaving.

Not sure where one would have figured that out from any documentation (and I honestly still don't really understand what's going on here), but hey now it's here for those who end up here by googling, thanks @bkudria!

In rails 4.2.9, Rspec 3.6, I had to do post :create, params.merge(format: :json) to make it work. This was very annoying!!

Was this page helpful?
0 / 5 - 0 ratings