8

When I send an object json all fields inside are changed to string, breaking my validation in the controller and i get the following error.

Api::V1::BillsController POST #create when logged in 
     Failure/Error: post :create, { bill: bill_attributes }
     Apipie::ParamInvalid:
       Invalid parameter 'value' value "41.64794235693306": Must be Float
     # ./app/controllers/concerns/exception_aspects.rb:4:in exception_wrapper
     # ./spec/controllers/api/v1/bills_controller_spec.rb:135:in block (4 levels) in <top (required)>

My test I try indicate request.headers['Content-Type'] = 'application/json'

let(:bill_attributes) { FactoryGirl.attributes_for :bill }

before(:each) do
   request.headers['Content-Type'] = 'application/json'
   post :create, { bill: bill_attributes }
end

it "when is valid description" do
    expect(json_response[:description]).to eq(bill_attributes[:description])
end

My factory is

FactoryGirl.define do
 factory :bill do
  description { FFaker::Lorem.phrase }
  value { (rand() * 100).to_f }
 end
end

My controller validations are

api :POST, "/bills", "Add a new bill to an event"
description "Add a new bill"
param :bill, Hash, :required => true, :action_aware => true do
    param :description, String, "Bill description"
    param :bill_photo, Hash, :required => false do
        param :base64image, String, "Base 64 image file"
    end
    param :value, Float, "Amount of the bill"
end

I try to change validation :value from Float to :number but the problem continues

I am using rails 4.2.3 and rspec 3.3.0

4
  • I thought all parameters were submitted as strings. How will a float be submitted to the api? Commented Nov 19, 2015 at 16:46
  • 1
    @Swards I try to send an object json { bill: { description: 'this is description', value:52.54 } } Commented Nov 20, 2015 at 0:43
  • If you look at the params hash in the controller, all the params will be strings. You can test if the format of the string would be a valid float Commented Nov 20, 2015 at 5:40
  • If your json-consumer is expecting a non-string value, the controller-action will fail, and testing is not possible. Commented Aug 19, 2019 at 8:47

5 Answers 5

23
post :create, params: {}, as: :json

This is what works in Rails 5.0.3 and rspec-rails 3.6.0

Rails controller specs now inherit from ActionDispatch::IntegrationTest instead of ActionController::TestCase. But RSpec controller specs still use ActionController::TestCase which is deprecated. Relevant Rails commit here

Sign up to request clarification or add additional context in comments.

1 Comment

But "as: :json" with "post" converts my integers to strings.
3

I added format json to post request and It worked like charm

before(:each) do
   post :create, { bill: bill_attributes, format: :json }
end

1 Comment

This doesn't work anymore. RajeshT has the right answer.
1

None of above works for me.(rails 5.1.7, rspec 3.6)
The simple way you can give it a try is stub ActionController::Parameters In my case, in controller I always use permit for strong parameters.

def product_parameters
  _params = params.permit :name, :price

  # validate for price is integer
  raise BadRequest, code: 'blah_code' unless _params[:price].is_a?(Integer)
end

and then in Rspec I stub ActionController::Parameters like below

allow_any_instance_of(ActionController::Parameters).to receive(:permit).and_return(ActionController::Parameters.new(name: 'product name', price: 3000).permit(:name, :price)

just like that, and Rspec test checking Integer will work

NOTE: This can also apply with send boolean, float in params too.

Comments

1

In my case using rails 4.2, rspec 3.5 and ruby 2.3

post '/api/webhooks/v1/subscriptions', { abc: 134 }.to_json, headers

the to_json part is the most important here and the headers have:

let(:headers) do
  {
    'Authorization' => 'Basic my-token',
    'Content-Type' => 'application/json'
  }
end

Comments

0

For Rails 4 We can try this

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.