요청 사양을 작성할 때 세션 및 / 또는 스텁 컨트롤러 메서드를 어떻게 설정합니까? 통합 테스트에서 인증 스텁을 시도하고 있습니다-rspec / requests
다음은 테스트의 예입니다.
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
그리고 인증을 처리하는 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
) 컨트롤러 사양처럼 작동하지 않는 씬 래퍼 입니다. 사용 가능한 세션 메서드가 있지만 지원되지 않는다고 생각합니다 (즉, 다른 유틸리티에 포함되는 모듈에도 해당 메서드가 포함되어 있기 때문에있을 수 있습니다).
사용자 인증에 사용하는 모든 작업에 게시하여 로그인하는 것이 좋습니다. 모든 사용자 팩토리에 대해 암호를 ‘password'(예 :)로 지정하면 다음과 같이 할 수 있습니다.
def 로그인 (사용자) post login_path, : login => user.login, : password => 'password' 종료
답변
Devise 사용자를위한 참고 사항 …
BTW, @David Chelimsky의 답변은 Devise를 사용하는 경우 약간의 조정이 필요할 수 있습니다 . 통합 / 요청 테스트에서 내가하는 일 ( 이 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 :: Unit 테스트를 RSpec으로 포팅 할 때 요청 사양에서 여러 세션 (개발)으로 로그인 할 수 있기를 원했습니다. 파는 데 약간의 시간이 걸렸지 만이 작업을 수행했습니다. 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>)
모든 루비 특수 연산자는 실제로 메서드입니다. 호출은와 1+1
동일 합니다. 1.+(1)
즉 +
, 메서드 일뿐입니다. 마찬가지로, session[:user_id]
메소드를 호출하는 것과 동일 []
상 session
으로,session.[](:user_id)
답변
나는 이것이 Devise에 매우 유용하다는 것을 알았습니다 : https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)