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

如何用RSpec测试Devise登录功能中的reCAPTCHA有效性?

问题:如何编写RSpec测试验证Devise登录功能中的reCAPTCHA有效性?

我目前有一段RSpec测试代码:

context '#update_password' do
  it 'current_user can update his password' do
    user = FactoryBot.create :user
    sign_in user
    put :update_password, xhr: true, params: { id: user.id, user: { id: user.id, current_password: user.password, password: 'ValidPass1!' } }
    expect(response).to be_success
  end
end

现在需要编写测试来验证Devise登录流程里reCAPTCHA的有效性,我使用的是 gem 'recaptcha', require: 'recaptcha/rails' 这个gem。


解决方案

刚好我之前处理过类似的需求,给你分享下具体的测试思路和代码示例吧!

首先得明确,我们需要覆盖几个核心场景:reCAPTCHA验证通过时登录成功、验证失败时被阻止,还要注意测试环境的reCAPTCHA默认配置——它会自动跳过验证,所以得先调整这个设置才能让测试真正生效。

1. 先确保测试环境能触发reCAPTCHA验证

默认情况下,recaptcha gem在test环境会直接跳过验证,这样我们的测试就测不到真实逻辑了。可以在单个测试块里临时开启验证,测试结束后再恢复,避免影响其他测试:

context 'POST #create (login with reCAPTCHA)' do
  before do
    # 移除test环境的跳过验证设置
    Recaptcha.configuration.skip_verify_env.delete('test')
  end

  after do
    # 测试完成后恢复默认配置
    Recaptcha.configuration.skip_verify_env << 'test'
  end

  # 下面放具体测试用例
end

2. 编写具体的登录测试用例

假设你的登录接口是Devise默认的/users/sign_in(对应devise/sessions#create动作),我们分场景来写:

场景1:reCAPTCHA验证通过,成功登录

let(:user) { FactoryBot.create(:user, email: 'test@example.com', password: 'ValidPass1!') }

it 'logs in successfully when reCAPTCHA is valid' do
  # Mock reCAPTCHA的验证结果为通过
  allow_any_instance_of(Recaptcha::Verify).to receive(:verify_response).and_return(true)
  
  post '/users/sign_in', params: {
    user: {
      email: user.email,
      password: user.password
    },
    'g-recaptcha-response': 'any_valid_token' # 这里随便填,因为我们已经mock了验证
  }

  expect(response).to redirect_to(root_path) # 替换成你实际的登录成功跳转路径
  expect(session[:user_id]).to eq(user.id)
end

场景2:reCAPTCHA验证失败,登录被阻止

it 'blocks login when reCAPTCHA is invalid' do
  # Mock验证失败的结果
  allow_any_instance_of(Recaptcha::Verify).to receive(:verify_response).and_return(false)
  
  post '/users/sign_in', params: {
    user: {
      email: user.email,
      password: user.password
    },
    'g-recaptcha-response': 'invalid_token'
  }

  expect(response).to render_template('devise/sessions/new') # 停留在登录页面
  expect(flash[:alert]).to include('reCAPTCHA验证失败') # 替换成你实际的提示文本
  expect(session[:user_id]).to be_nil
end

场景3:未提供reCAPTCHA响应,登录被阻止

it 'blocks login when reCAPTCHA response is missing' do
  post '/users/sign_in', params: {
    user: {
      email: user.email,
      password: user.password
    }
    # 不传入g-recaptcha-response参数
  }

  expect(response).to render_template('devise/sessions/new')
  expect(flash[:alert]).to include('请完成reCAPTCHA验证') # 替换成实际提示
end

3. 自定义Devise控制器的注意事项

如果你是自己写了继承自Devise::SessionsController的自定义控制器,得确保控制器里已经加上了reCAPTCHA的验证逻辑,比如:

class SessionsController < Devise::SessionsController
  def create
    if verify_recaptcha
      super # 调用Devise默认的登录逻辑
    else
      flash.now[:alert] = 'reCAPTCHA验证失败,请重试'
      render :new
    end
  end
end

只有控制器里有这段逻辑,上面的测试用例才能准确验证你的业务流程哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:14:30