When writing a request spec, how do you set sessions and/or stub controller methods? I'm trying to stub out authentication in my integration tests - rspec/requests
Here's an example of a test
require File.dirname(__FILE__) + '/../spec_helper' require File.dirname(__FILE__) + '/authentication_helpers' describe "Messages" do include AuthenticationHelpers describe "GET admin/messages" do before(:each) do @current_user = Factory :super_admin login(@current_user) end it "displays received messages" do sender = Factory :jonas direct_message = Message.new(:sender_id => sender.id, :subject => "Message system.", :content => "content", :receiver_ids => [@current_user.id]) direct_message.save get admin_messages_path response.body.should include(direct_message.subject) end end end
The helper:
module AuthenticationHelpers def login(user) session[:user_id] = user.id # session is nil #controller.stub!(:current_user).and_return(user) # controller is nil end end
And the ApplicationController that handles authentication:
class ApplicationController < ActionController::Base protect_from_forgery helper_method :current_user helper_method :logged_in? protected def current_user @current_user ||= User.find(session[:user_id]) if session[:user_id] end def logged_in? !current_user.nil? end end
Why is it not possible to access these resources?
1) Messages GET admin/messages displays received messages Failure/Error: login(@current_user) NoMethodError: undefined method `session' for nil:NilClass # ./spec/requests/authentication_helpers.rb:3:in `login' # ./spec/requests/message_spec.rb:15:in `block (3 levels) in <top (required)>'
A request spec is a thin wrapper around ActionDispatch::IntegrationTest
, which doesn't work like controller specs (which wrap ActionController::TestCase
). Even though there is a session method available, I don't think it is supported (i.e. it's probably there because a module that gets included for other utilities also includes that method).
I'd recommend logging in by posting to whatever action you use to authenticate users. If you make the password 'password' (for example) for all the User factories, then you can do something like this:
def login(user) post login_path, :login => user.login, :password => 'password' end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With