请求规范中的存根authentication

在编写请求规范时,如何设置会话和/或存根控制器方法? 我试图在我的集成testing – RSpec /请求存根validation

这是一个testing的例子

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 

帮手:

 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 

和处理authentication的ApplicationController:

 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 

为什么不能访问这些资源?

 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)>' 

请求规范是ActionDispatch::IntegrationTest一个简单的包装器,它不像控制器规范那样工作(包装ActionController::TestCase )。 即使有一个会话方法可用,我不认为这是支持的(即它可能是因为一个模块,包括其他实用程序还包括该方法)。

我build议通过发布到您用来validation用户的任何操作login。 如果你为所有用户工厂设置了密码(例如),那么你可以这样做:

 def login(user)
   post login_path,:login => user.login,:password =>'password'
结束

顺便说一句,@David Chelimsky的答案可能需要一点调整,如果你使用Devise。 我在集成/请求testing中做了什么(感谢这个StackOverflow后 ):

 # file: spec/requests_helper.rb def login(user) post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password end 

FWIW,在将我的Test :: Unittesting移植到RSpec时,我希望能够在请求规范中使用多个(devise)会话进行login。 它采取了一些挖掘,但得到这个为我工作。 使用Rails 3.2.13和RSpec 2.13.0。

 # file: spec/support/devise.rb module RequestHelpers def login(user) ActionController::IntegrationTest.new(self).open_session do |sess| u = users(user) sess.post '/users/sign_in', { user: { email: u.email, password: 'password' } } sess.flash[:alert].should be_nil sess.flash[:notice].should == 'Signed in successfully.' sess.response.code.should == '302' end end end include RequestHelpers 

和…

 # spec/request/user_flows.rb require 'spec_helper' describe 'User flows' do fixtures :users it 'lets a user do stuff to another user' do karl = login :karl karl.get '/users' karl.response.code.should eq '200' karl.xhr :put, "/users/#{users(:bob).id}", id: users(:bob).id, "#{users(:bob).id}-is-funny" => 'true' karl.response.code.should eq '200' User.find(users(:bob).id).should be_funny bob = login :bob expect { bob.get '/users' }.to_not raise_exception bob.response.code.should eq '200' end end 

编辑 :固定错字

你也可以非常轻松地存储会话。

 controller.session.stub(:[]).with(:user_id).and_return(<whatever user ID>) 

所有的ruby特殊操作符的确是方法。 调用1+11.+(1) ,这意味着+只是一种方法。 类似地, session[:user_id]session上调用method []相同,因为session.[](:user_id)

我发现这对devise非常有帮助: https : //github.com/plataformatec/devise/wiki/How-To :-Test-controllers-with-Rails-3-and-4-(and-RSpec )