如何用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
相关产品推荐
相关产品推荐

