1

I'm trying to make a test to submit JSON data to my API endpoint, however it's not working. After trying various suggestions from blogs and the rspec documentation I'm still failing.

specs/controller/v1/devices_controller_spec.rb

require 'rails_helper' RSpec.describe V1::DevicesController, type: :controller do it "updates device info" do @data = {} @device = FactoryGirl.create(:device) @data[:diagnostic_dns] = false @data[:diagnostic_ping] = false put :update, @data.to_json @data.reload response.should be_successful end end 

I've also tried this in my test:

 it "updates device info" do device = FactoryGirl.create(:device) device.diagnostic_dns = false device.diagnostic_ping = false put :update, :device, :format => :json response.should be_successful end 

Which results in this rspec failure:

Failures: 1) V1::DevicesController updates device info Failure/Error: put :update, @data.to_json ArgumentError: wrong number of arguments (given 2, expected 1) 

app/controllers/v1/devices_controller.rb

class V1::DevicesController < ApplicationController skip_before_action :authenticate_user!, only: [:show, :update], :if => Proc.new { |c| c.request.format == 'application/json' } before_action :set_device, only: [:show, :update] respond_to :json def update if @device.update(device_params) render json: @device, status: :ok else render json: @device.errors, status: :unprocessable_entity end end private def set_device @device = Device.find_by!(serial_number: params[:serial_number]) end def device_params params.require(:device).permit( :serial_number, :name, :diagnostic_checkin_status, :diagnostic_dns, :diagnostic_ping, ) end end 

And my routes.rb file

 v1_device GET /v1/devices/:serial_number(.:format) v1/devices#show PATCH /v1/devices/:serial_number(.:format) v1/devices#update PUT /v1/devices/:serial_number(.:format) v1/devices#update 

UPDATE After changing my test submit to:

patch :update, params: {serial_number: device.serial_number, device: @data }, :format => :json 

I'm now getting:

Failures: 1) V1::DevicesController updates device info Failure/Error: response.should be_successful expected `#<ActionDispatch::TestResponse:0x005592458af9d0 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Thread::Mu...:Headers:0x00559245826d10 @req=#<ActionController::TestRequest:0x005592458afcc8 ...>>, @variant=[]>>.successful?` to return true, got false 

UPDATE I added byebug to the controller and this is what @device.errors has it in:

@messages={:diagnostic_ping=>["can't be blank"], :diagnostic_dns=>["can't be blank"]}, @details={:diagnostic_ping=>[{:error=>:blank}], :diagnostic_dns=>[{:error=>:blank}]}> 

So, the variables are not being set?

2
  • How're you validating the presence of those fields? I assume they're boolean and with just this information I'm going to guess you're likely doing validates_presence_of :diagnostic_ping, which the docs warn about Commented Jul 9, 2017 at 19:34
  • You're right, the validation was the issue. I removed it and the test passed. Commented Jul 9, 2017 at 19:54

2 Answers 2

1

To adding parameter, you can use this.

specs/controller/v1/devices_controller_spec.rb require 'rails_helper' RSpec.describe V1::DevicesController, type: :controller do let(:new_attributes) { FactoryGirl.attributes_for :device, diagnostic_dns: false, diagnostic_ping: false } it "updates device info" do @device = FactoryGirl.create :device put :update, params: {serial_number: @device.serial_number, device: new_attributes }, :format => :json response.should be_successful end end 

I hope this help you.

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

Comments

0

I wouldn't stress too much about getting RSpec to submit an actual JSON string to your code. Rails is in charge of turning that JSON into a params hash for you, so Rails should have the tests verifying they handle JSON properly. I would just do a normal test passing params with a format: :json verifying that you return the JSON you're expecting.

I believe that would look like

put :update, serial_number: @device.serial_number, device: @data, format: :json 

3 Comments

This particular route is used by remote hosts, so I want to make sure the controller is doing it's job correctly. Mainly, the remote host is building the JSON and submitting it to this API endpoint.
Right, but in your controller the only thing you had to do differently then any other web app was render json: ..., when it comes to looking at the params hash, rails already spotted it was JSON coming in and turned it into a params hash all the same for you, so you're none-the wiser about it being a JSON request. So, personally, I wouldn't worry too much about making sure your test passes in JSON, that to me is testing a rails feature, not my own code.
Gotcha... I updated my code above and used byebug. It doesn't look like my params are getting passed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.