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

Rails教程账户激活测试失败问题求助

Rails账户激活测试失败排查

嘿,咱们来搞定这个测试失败的问题!我最近跟着在线Rails教程学习时,碰到了一模一样的账户激活测试失败情况,具体错误和相关代码如下:

测试失败报错信息

FAIL["test_valid_signup_information_with_account_activation", UsersSignupTest, 5.62457 6674999844]
test_valid_signup_information_with_account_activation#UsersSignupTest (5.63s)
Expected false to be truthy.
test/integration/users_signup_test.rb:38:in block in <class:UsersSignupTest>

测试文件代码(test/integration/users_signup_test.rb)

require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest
  def setup
    ActionMailer::Base.deliveries.clear
  end

  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post users_path, params: { user: { name: "",
                                         email: "user@invalid",
                                         password: "foo",
                                         password_confirmation: "bar" } }
    end
    assert_template 'users/new'
    assert_select 'div#error_explanation'
    assert_select 'div.field_with_errors'
  end

  test "valid signup information with account activation" do
    get signup_path
    assert_difference 'User.count', 1 do
      post users_path, params: { user: { name: "Example User",
                                         email: "user@example.com",
                                         password: "foobar12",
                                         password_confirmation: "foobar12" } }
    end
    assert_equal 1, ActionMailer::Base.deliveries.size
    user = assigns(:user)
    assert_not user.activated?
    # 尝试在激活前登录
    log_in_as(user)
    assert_not is_logged_in?
    # 无效的激活令牌
    get edit_account_activation_path("invalid token")
    assert_not is_logged_in?
    # 有效令牌,但邮箱错误
    get edit_account_activation_path(user.activation_token, email: 'wrong')
    assert_not is_logged_in?
    # 有效激活令牌
    get edit_account_activation_path(user.activation_token, email: user.email)
    assert user.reload.activated? # 👉 问题就出在这一行,预期激活为true但实际是false
    follow_redirect!
    assert_template 'users/show'
    assert is_logged_in?
  end
end

账户激活控制器代码(app/controllers/account_activations_controller.rb)

class AccountActivationsController < ApplicationController
  def edit
    user = User.find_by(email: params[:email])
    if user && !user.activated? && user.authenticated?(:activation, params[:id])
      # user.activate  # 这里被注释掉了,是不是问题所在?
      user.update_attribute(:activated, true)
      user.update_attribute(:activated_at, Time.zone.now)
      log_in user
      flash[:success] = "Account activated!"
      redirect_to user
    else
      flash[:danger] = "Invalid activation link"
      redirect_to root_url
    end
  end
end

问题排查与修复思路

我当时碰到这个问题时,主要从这几个方向排查,你可以逐一检查:

1. 确认控制器激活逻辑是否执行

先判断请求edit_account_activation_path时,控制器里的激活代码块(if分支内的代码)是否真的被触发。你可以临时加调试输出验证:

def edit
  user = User.find_by(email: params[:email])
  puts "找到的用户:#{user.inspect}"
  puts "用户未激活?#{!user.activated?}" if user
  puts "令牌验证通过?#{user.authenticated?(:activation, params[:id])}" if user
  if user && !user.activated? && user.authenticated?(:activation, params[:id])
    # ... 原有代码
    puts "激活代码执行了!"
  else
    puts "进入错误分支了!"
  end
end

运行测试后看终端输出,就能知道是否进入了正确的分支。

2. 验证authenticated?方法正确性

User模型里的authenticated?方法必须正确处理:activation类型,标准实现应该是这样的:

def authenticated?(attribute, token)
  digest = send("#{attribute}_digest")
  return false if digest.nil?
  BCrypt::Password.new(digest).is_password?(token)
end

如果方法参数顺序错误、未正确调用activation_digest,会导致令牌验证失败,跳过激活逻辑。

3. 检查用户创建时的激活字段初始化

用户创建时,必须通过回调生成activation_token和activation_digest,并默认设置activated: false。你的User模型应该包含以下代码:

before_create :create_activation_digest

private

def create_activation_digest
  self.activation_token  = User.new_token
  self.activation_digest = User.digest(activation_token)
end

# 生成随机token和加密的工具方法
def self.new_token
  SecureRandom.urlsafe_base64
end

def self.digest(string)
  cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
  BCrypt::Password.create(string, cost: cost)
end

如果这些回调或方法缺失,用户的activation_digest会是nil,导致authenticated?返回false,激活逻辑不执行。

4. 确认数据库字段存在

确保users数据表有activated(布尔型,默认false)和activated_at(datetime型,默认nil)两个字段。如果字段缺失,update_attribute会静默失败(Rails不报错但数据不写入),导致user.reload.activated?仍为false。

5. 恢复user.activate方法(如果有定义)

如果你的User模型里定义了activate方法(一次性更新两个字段):

def activate
  update_columns(activated: true, activated_at: Time.zone.now)
end

建议取消注释user.activate,删掉下面两个update_attribute调用,这种方式更高效且不易出错,可能直接解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:58:37