问题
I'm trying to run a test for rendering templates and ran into the error:
undefined method `key?' for 1014:Fixnum
The stub of my model's instance works as it should in my route tests but not so much here. What am I doing wrong?
describe RestaurantsController do
let(:restaurant) { FactoryGirl.build_stubbed(:restaurant) }
describe 'GET #show' do
before { get :show, restaurant.id }
it { should render_template('show') }
end
end
Full Error
1) RestaurantsController GET #show
Failure/Error: before { get :show, restaurant.id }
NoMethodError:
undefined method `key?' for 1014:Fixnum
# /Library/Ruby/Gems/2.0.0/gems/actionpack-4.2.0/lib/action_controller/test_case.rb:744:in `html_format?'
# /Library/Ruby/Gems/2.0.0/gems/actionpack-4.2.0/lib/action_controller/test_case.rb:598:in `process'
# /Library/Ruby/Gems/2.0.0/gems/actionpack-4.2.0/lib/action_controller/test_case.rb:65:in `process'
# /Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/lib/devise/test_helpers.rb:19:in `block in process'
# /Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/lib/devise/test_helpers.rb:72:in `catch'
# /Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/lib/devise/test_helpers.rb:72:in `_catch_warden'
# /Library/Ruby/Gems/2.0.0/gems/devise-3.5.1/lib/devise/test_helpers.rb:19:in `process'
# /Library/Ruby/Gems/2.0.0/gems/actionpack-4.2.0/lib/action_controller/test_case.rb:505:in `get'
# ./spec/controllers/restaurants_controller_spec.rb:15:in `block (3 levels) in <top (required)>'
回答1:
get
takes a action and hash of params (among other things). It will not implicitly take a model and turn it into { id: model.to_param }
.
Instead you need to specify the parameters explicitly.
describe RestaurantsController do
let(:restaurant) { create(:restaurant) }
subject { response }
describe 'GET #show' do
before { get :show, id: restaurant }
it { should render_template('show') }
end
end
As @Зелёный has already mentioned you need to actually persist the record to the database to be able to use it in a controller spec.
To avoid the duplication issue and test ordering issues you should empty the database between each example. The database_cleaner gem is invaluable for that task.
Also if you need to create several records in the same spec you can use sequences in factory girl:
FactoryGirl.define do
factory :user do
email { |n| "test-#{n}@example.com" }
end
end
The gem ffaker is great for generating emails, usernames etc.
Added:
You can setup shortcuts for FactoryGirl by including its methods in your rails_helper
:
RSpec.configure do |config|
# ...
config.include FactoryGirl::Syntax::Methods
end
This lets you use the FactoryGirl methods without typing the module name like so:
let(:restaurant) { create(:restaurant) }
来源:https://stackoverflow.com/questions/31765624/rspec-undefined-method-key