You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RSpec测试用户认证前置问题:编辑接口重定向至登录页异常

解决RSpec测试中用户未激活导致登录失败的问题

方案1:修改FactoryBot用户工厂,默认创建已激活用户

修改用户工厂文件,添加激活状态和激活时间的默认值,让所有通过FactoryBot创建的用户默认处于已激活状态:

# spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name { "Example User" }
    email { "user@example.com" }
    password { "password" }
    password_confirmation { "password" }
    # 添加以下两行,设置默认激活状态
    activated { true }
    activated_at { Time.zone.now }
  end
end

修改后,原测试代码无需额外改动,let(:user) { FactoryBot.create(:user) }创建的用户会自动激活,log_in_as(user)能成功登录,测试会按预期重定向到用户页面。

方案2:在测试中手动激活特定用户

如果不想修改默认工厂(比如其他测试需要未激活用户),可以在当前测试里手动激活用户:

方式A:创建用户时直接设置激活状态

describe "PATCH /users/:id" do
  # 创建用户时直接激活
  let(:user) { FactoryBot.create(:user, activated: true, activated_at: Time.zone.now) }

  before { log_in_as(user) }

  it 'Successful edit with valid information entered' do
    patch user_path(user), params: { user: {
      name: "Foo Bar",
      email: "foo@bar.com",
      password: "",
      password_confirmation: "",
    } }
    expect(response).to redirect_to user_path(user)
  end
end

方式B:在before块中激活用户

describe "PATCH /users/:id" do
  let(:user) { FactoryBot.create(:user) }

  before do
    # 手动激活用户
    user.update!(activated: true, activated_at: Time.zone.now)
    log_in_as(user)
  end

  it 'Successful edit with valid information entered' do
    patch user_path(user), params: { user: {
      name: "Foo Bar",
      email: "foo@bar.com",
      password: "",
      password_confirmation: "",
    } }
    expect(response).to redirect_to user_path(user)
  end
end

方案3:优化log_in_as辅助方法,支持自动激活

修改集成辅助方法,添加activate参数,默认激活用户,测试时可灵活控制:

# spec/support/integration_helpers.rb
module IntegrationHelpers
  def is_logged_in?
    !session[:user_id].nil?
  end

  def log_in_as(user, password: 'password', remember_me: '1', activate: true)
    # 如果需要激活且用户未激活,更新激活状态
    if activate && !user.activated?
      user.update!(activated: true, activated_at: Time.zone.now)
    end
    post login_path, params: { session: { 
      email: user.email,
      password: password,
      remember_me: remember_me 
    } }
  end
end

使用时,默认调用log_in_as(user)会自动激活用户;若需测试未激活场景,调用log_in_as(user, activate: false)即可。

问题原因说明

测试失败的核心原因:

  1. FactoryBot创建的用户默认未激活
  2. SessionsController#create动作只允许已激活用户登录,未激活用户会被重定向到root_url,导致实际未登录成功
  3. 用户编辑接口(PATCH /users/:id)存在登录验证(比如before_action :logged_in_user),未登录状态下会重定向到登录页,因此出现期望重定向到用户页面、实际到登录页的错误

内容的提问来源于stack exchange,提问作者show_2083

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:47:24