Reputation: 329
New to RSpec and having trouble stubbing out an update method (needs to be stubbed) and am running into this error. I have tried a bunch of different ways and can't seem to solve it. I tried to include only the necessary code.
/spec/controllers/admin/business_controller_spec.rb
:
require 'spec_helper'
RSpec.describe Admin::BusinessesController, type: :controller do
render_views
before(:all) do
@business = build_stubbed(:business)
end
describe '#update' do
before(:each) do
allow(Business).to receive(:find).and_return(@business)
@new_name = Faker::Company.name
@params = { id: @business.id, business: { name: @new_name } }
end
it 'updates business name' do
expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: @business.confirm_flag, phone_primary: @business.phone_primary).and_return(true)
xhr :patch, :update, id: @business.id, business: { name: @new_name }
expect(@business.name).to eq(@new_name)
end
end
end
/app/controllers/admin/businesses_controller.rb
class Admin::BusinessesController < Admin::BaseAdminController
def update
@business.update_attributes(business_params)
end
def business_params
params.require(:business).permit(:name, :active_flag).merge(confirm_flag: true, phone_primary: '')
end
end
When I run this test I get this error:
Failures:
1) Admin::BusinessesController#update updates business name
Failure/Error: @business.update_attributes(business_params)
#<Business:0x007fc43c4f5738> received :update_attributes with unexpected arguments
expected: ({:name=>"Fadel, Larson and Hettinger", :confirm_flag=>true, :phone_primary=>"7832900175"})
got: ({"name"=>"Fadel, Larson and Hettinger", "confirm_flag"=>true, "phone_primary"=>""})
Diff:
@@ -1,4 +1,4 @@
-[{:name=>"Fadel, Larson and Hettinger",
- :confirm_flag=>true,
- :phone_primary=>"7832900175"}]
+[{"name"=>"Fadel, Larson and Hettinger",
+ "confirm_flag"=>true,
+ "phone_primary"=>""}]
So it looks like the phone_primary
is causing the problem and I change my test expectation line to be:
describe '#update' do
before(:each) do
allow(Business).to receive(:find).and_return(@business)
@new_name = Faker::Company.name
@params = { id: @business.id, business: { name: @new_name } }
end
it 'updates business name' do
expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: @business.confirm_flag, **phone_primary: ''**).and_return(true)
xhr :patch, :update, id: @business.id, business: { name: @new_name }
expect(@business.name).to eq(@new_name)
end
end
and i get the failure:
Failures:
1) Admin::BusinessesController#update updates business name
Failure/Error: expect(@business.name).to eq(@new_name)
expected: "Flatley Inc"
got: "Samara Kuhic"
And now the names aren't matching
Upvotes: 1
Views: 4972
Reputation: 329
I ended up stubbing the reload by using assigns. My tests are now passing with this:
describe '#update' do
before(:each) do
allow(Business).to receive(:find).and_return(@business)
@new_name = Faker::Company.name
end
it 'updates business name' do
expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: true, phone_primary: '').and_return(@business)
xhr :patch, :update, id: @business.id, business: { name: @new_name }
expect(assigns(:business)).to eq(@business)
expect(response.status).to eq(200)
end
end
Not sure if this is the preferred way but it's passing for me. Looks like assigns
will be deprecated in Rails 5
Upvotes: 2
Reputation: 1489
If you check your original code, in your controller you have this:
def business_params
params.require(:business).permit(:name, :active_flag).merge(confirm_flag: true, phone_primary: '')
end
you're always setting confirm_flag
to true
and phone_primary
to ''
(empty string). And in your test you have this:
expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: @business.confirm_flag, phone_primary: @business.phone_primary).and_return(true)
so, if you check confirm_flag
you're setting it to @business.confirm_flag
which in this case in fact is true
and it's fine with what you're setting in the controller, but the problem comes with phone_primary
which is being set to @business.phone_primary
, and in this case @business.phone_primary
is 7832900175
, and that's why it is failing.
So, to fix this, you either have to change your test to:
expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: @business.confirm_flag, phone_primary: '').and_return(true)
or change your controller code to permit
phone_primary
from the params, which will also fix your error.
Upvotes: 0