Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails, Devise, Rspec: Undefined method 'sign_in'

I am trying to write Rspec tests in Rails, using Devise helper methods for signing in and out. The sign_in method is not working. However, it had been working earlier, before a slew of changes to the app.

Things I have tried:

  • I am including the test helpers in Rspec.configure.
  • Using Warden's login_as
  • Clearing the Rails cache.
  • Getting rid of Capybara to see if that were causing the issue
  • I am not setting the session explicitly in my controller specs (e.g. no valid_session)

So far, no dice. What do I need to do differently to test my controllers with a signed-in user?

Error message:

 OrderItemsController GET #index renders the :index view  Failure/Error: sign_in :admin  NoMethodError:       undefined method `sign_in' for #  <RSpec::ExampleGroups::OrderItemsController_2::GETIndex:0x00000102c002d0>  # ./spec/controllers/order_items_controller_spec.rb:6:in `block (2 levels) in <top (required)>' 

Controller Spec

require 'spec_helper'  describe OrderItemsController do     before (:each) do         admin = create(:admin)         sign_in :admin     end      describe "GET #index" do         it "renders the :index view" do             get :index             expect( response ).to render_template :index         end     end end 

spec_helper.rb

require 'rspec/rails' require 'capybara/rspec'  RSpec.configure do |config|    config.include ApplicationHelper   config.include ControllersHelper   config.include UsersHelper   config.include Devise::TestHelpers, type: :controller   config.include FactoryGirl::Syntax::Methods  end 

Gemfile

group :development, :test do     gem 'rspec-rails', '~> 3.0.0.beta'     gem 'capybara'     gem 'factory_girl_rails'     gem 'faker'     gem 'dotenv-rails'     gem 'guard'     gem 'guard-annotate'     gem 'guard-rspec', require: false     gem 'guard-livereload', require: false     gem 'foreman' end 

factories/user.rb

FactoryGirl.define do      factory :user do         first                   { Faker::Name.first_name }         last                    { Faker::Name.last_name }         email                   { Faker::Internet.email }         admin                   false         password                "secrets1"         password_confirmation   "secrets1"         confirmed_at            Date.today          factory :admin do             admin               true         end     end end 

Thanks in advance.

like image 996
steel Avatar asked May 25 '14 20:05

steel


2 Answers

Did you recently upgrade to RSpec 3 like I did? This is from the RSpec 3 documentation:

Automatically Adding Metadata RSpec versions before 3.0.0 automatically added metadata to specs based on their location on the filesystem. This was both confusing to new users and not desirable for some veteran users.

In RSpec 3, this behavior must be explicitly enabled:

​# spec/rails_helper.rb RSpec.configure do |config|     config.infer_spec_type_from_file_location! end 

Since this assumed behavior is so prevalent in tutorials, the default configuration generated by rails generate rspec:install enables this.

If you follow the above listed canonical directory structure and have configured infer_spec_type_from_file_location!, RSpec will automatically include the correct support functions for each type.

After I add that configuration snippet, I no longer have to specify the spec type (e.g. type: :controller).

like image 110
Tyler Collier Avatar answered Oct 02 '22 23:10

Tyler Collier


I figured out a solution. I explicitly defined the controller's Describe block as a controller type.

describe OrderItemsController, :type => :controller do 

I still don't understand why this code worked earlier but now needs this (seemingly redundant) explicit declaration. Regardless, I'd appreciate learning what happened here. Thanks!

like image 31
steel Avatar answered Oct 03 '22 00:10

steel