Reputation: 15104
For some reason, I can not get the devise helper method sign_in to work. current_user keeps on being null. Any idea what the problem could be?
Test:
before :each do
@user = FactoryGirl.create :user
sign_in @user
end
describe "GET index" do
it "assigns all subscribers as @subscribers" do
subscriber = @user.subscribers.create! valid_attributes
get :index
assigns(:subscribers).should eq([subscriber])
end
end
Implementation:
def index
@subscribers = current_user.subscribers.all <------- ERROR
respond_to do |format|
format.html # index.html.erb
format.json { render json: @subscribers }
end
end
Error:
NoMethodError:
undefined method `subscribers' for nil:NilClass
Any help is appreciated. Thanks!
Upvotes: 14
Views: 12676
Reputation: 12335
For versions of Devise 4.2.0+, the Devise::TestHelpers
have been deprecated. Instead, Devise::Test::ControllerHelpers
should be used.
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, type: :controller
end
For the spec, make sure to include Devise::TestHelpers
. To make it easy, in my spec/spec_helper.rb, I have:
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
which automatically includes it for all controller specs.
Also, you need to do this to get sign_in to work:
@request.env["devise.mapping"] = Devise.mappings[:user]
get :new
It is probably best to add @request.env["devise.mapping"] = Devise.mappings[:user]
to your before(:each). (Note you can do this in your config if you don't want to do this for every controller).
For the current_user
part, make sure you have a model User
, where you call devise
class User < ActiveRecord::Base
# call devise to define user_signed_in? and current_user
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
# though you don't have to include all these modules
end
Devise uses the call in the User model to define user_signed_in?
and current_user
in your controllers. The reason is that if you have:
class Admin < ActiveRecord::Base
devise
end
then Devise will have methods admin_signed_in?
and current_admin
defined.
Upvotes: 6
Reputation: 2525
I encountered this problem when trying to test that an SSO endpoint I was writing was creating an session for a user. Since it only applied to one test, I just needed to add the following block before my test
before do
@request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryGirl.create(:user, :email => email, :password => "password")
user.confirm!
end
it "should create and session for the user and redirect to home page" do
Upvotes: 0
Reputation: 30256
If you include the Confirmable
module in your User
model (or other devise-authenticatable model), then the test @user
you create must be confirmed for the sign_in
to take effect:
before :each do
@user = FactoryGirl.create :user
@user.confirm!
sign_in @user
end
(I see that this wasn't your issue, but perhaps another reader shall benefit from it.)
Upvotes: 23
Reputation: 1012
Looks like you solved this, judging by your code. I have had this happen before, and for some reason it gets me every time.
The rspec/rails scaffold for controller specs won't work with Devise::TestHelpers out of the box.
get :index, {}, valid_session
The valid_session call overwrites the session stuff that Devise sets up. Remove it:
get :index, {}
This should work!
Upvotes: 12