Rails集成测试重定向后Session无法访问的问题
Rails集成测试中OmniAuth登录后Session不持久化的问题
问题场景
使用Rails IntegrationTest测试登录用户行为,通过OmniAuth Identity策略实现登录流程:
- 登录请求由
SessionsController#create处理,成功后设置session[:user_id]并重定向到首页 - 首页
WelcomeController#show根据current_user状态显示"Logged In"或"Logged Out" - 测试中登录请求执行后,Session在后续请求中丢失,始终显示未登录
相关代码
控制器代码
# Highly simplified logic for the login handler class SessionsController < ApplicationController def create auth_hash = request.env['omniauth.auth'] user = User.find_with_omniauth(auth_hash) session[:user_id] = user.id Rails.logger.debug(session.inspect) redirect_to root_path end end class WelcomeController < ApplicationController def show Rails.logger.debug(session.inspect) end end class ApplicationController < ActionController::Base def current_user @current_user ||= if session.key?(:user_id) User.find_by(id: session[:user_id]) else nil end end def logged_in? current_user.present? end end
测试代码
require 'test_helper' class WelcomeControllerTest < ActionDispatch::IntegrationTest include FactoryBot::Syntax::Methods setup do OmniAuth.config.test_mode = true end teardown do OmniAuth.config.test_mode = false OmniAuth.config.mock_auth[:identity] = nil end def manual_identity_log_in(user_with_identity) OmniAuth.config.mock_auth[:identity] = OmniAuth::AuthHash.new( { provider: 'identity', uid: user_with_identity.id, info: { email: user_with_identity.email, first_name: user_with_identity.first_name, last_name: user_with_identity.last_name, name: user_with_identity.full_name } }) post '/auth/identity/callback', params: {email: user_with_identity.email, password: ''} end test "can see the landing page for logged out users" do get "/" assert_select( "h1", "Logged Out") end test "can see the welcome page for logged in users" do current_user = create(:user_with_identity) manual_identity_log_in(current_user) get "/" assert_select( "h1", "Logged In") end end
解决方法
1. 跟随登录后的重定向
集成测试中,post请求默认不会自动跟随重定向,导致Session未被测试会话捕获。修改登录方法,添加follow_redirect!:
def manual_identity_log_in(user_with_identity) OmniAuth.config.mock_auth[:identity] = OmniAuth::AuthHash.new( { provider: 'identity', uid: user_with_identity.id, info: { email: user_with_identity.email, first_name: user_with_identity.first_name, last_name: user_with_identity.last_name, name: user_with_identity.full_name } }) post '/auth/identity/callback', params: {email: user_with_identity.email, password: ''} follow_redirect! # 确保测试会话获取到登录后的Session end
2. 确认测试环境Session存储配置
检查config/environments/test.rb,确保使用Cookie存储Session(默认配置),避免使用无法跨请求持久化的存储方式:
Rails.application.configure do # ... 其他配置 config.session_store :cookie_store, key: '_your_app_session' end
3. 验证登录请求的正确性
在测试中添加断言,确认登录请求执行成功,避免因请求失败导致Session未设置:
test "can see the welcome page for logged in users" do current_user = create(:user_with_identity) manual_identity_log_in(current_user) assert_response :success # 验证登录流程无错误 get "/" assert_select( "h1", "Logged In") end
内容的提问来源于stack exchange,提问作者andyroberts
相关产品推荐
相关产品推荐

