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

Rails7教程密码重置过期测试失败求助

Rails 7密码重置过期测试失败问题

我正在学习Rails 7版本的Ruby on Rails教程,完成12.3.3章节的第二个练习时遇到了问题。教程要求如下:

通过填写清单12.22中的模板,为清单12.16中的密码重置过期分支编写集成测试。(这段代码引入了response.body,它返回页面的完整HTML主体。)有多种方法可以测试过期结果,但清单12.22建议的方法是(不区分大小写)检查响应主体是否包含“expired”一词。

我的测试代码(password_resets_test.rb)

class PasswordResets < ActionDispatch::IntegrationTest

  def setup
    ActionMailer::Base.deliveries.clear
    @user = users(:one)
  end
end

class ExpiredToken < PasswordResets

  def setup
    super
    # 创建密码重置令牌
    post password_resets_path,
         params: { password_reset: { email: @user.email } }
    @reset_user = assigns(:user)
    # 手动让令牌过期
    @reset_user.update_attribute(:reset_sent_at, 3.hours.ago)
    # 尝试更新用户密码
    patch password_reset_path(@reset_user.reset_token),
          params: { email: @reset_user.email,
                    user: { password: 'foobar',
                            password_confirmation: 'foobar' } }
  end
end

class ExpiredTokenTest < ExpiredToken

  test '应重定向到密码重置页面' do
    assert_redirected_to new_password_reset_url
  end

  test "密码重置页面应包含'expired'关键词" do
    follow_redirect!
    assert_match /expired/i, response.body # ❌ 测试失败 ❌
  end
end

我反复核对教程内容,甚至从另一个成功实现的项目复制代码,但问题依然存在。以下是相关的核心代码:

路由配置(routes.rb)

resources :password_resets, only: [:new, :create, :edit, :update]

密码重置控制器(password_resets_controller.rb)

class PasswordResetsController < ApplicationController
  before_action :get_user, only: [:edit, :update]
  before_action :valid_user, only: [:edit, :update]
  before_action :check_expiration, only: [:edit, :update]


  def update
    if params[:user][:password].empty?
      @user.errors.add(:password, "不能为空")
      render 'edit', status: :unprocessable_entity
    elsif @user.update(user_params)
      @user.forget
      reset_session
      log_in @user
      flash[:success] = '密码已重置。'
      redirect_to @user
    else
      render 'edit', status: :unprocessable_entity
    end
  end

  def check_expiration
    if @user.password_reset_expired?
      flash[:danger] = '密码重置已过期。'
      redirect_to new_password_reset_url
    end
  end
end

可正常通过的测试用例(password_resets_test.rb)

def setup
  ActionMailer::Base.deliveries.clear
  @user = users(:one)
  post password_resets_path,
       params: { password_reset: { email: @user.email } }
  @reset_user = assigns(:user)
end


test '使用有效密码和确认密码更新' do
  patch password_reset_path(@reset_user.reset_token),
        params: { email: @reset_user.email,
                  user: { password: 'foobaz',
                          password_confirmation: 'foobaz' } }
  assert is_logged_in?
  assert_not flash.empty?
  assert_redirected_to @reset_user
end

密码重置页面视图(password_resets/new.html.erb)

<% provide(:title, "忘记密码") %>
<h1>忘记密码</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(url: password_resets_path, scope: :password_reset) do |f| %>
      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.submit "提交", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:15:46