Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing authentication in request spec

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)>' 
like image 917
Jonas Bylov Avatar asked Apr 26 '11 07:04

Jonas Bylov


1 Answers

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 
like image 197
David Chelimsky Avatar answered Sep 27 '22 21:09

David Chelimsky