Rails中Devise登录集成测试持续失败,报401未授权错误
嘿,我帮你梳理下这个Devise登录测试一直返回401的问题,既然你排除了语法错误,那大概率是测试配置或者请求细节没到位,给你几个针对性的排查方向:
检查Fixture加密密码的生成逻辑
你在fixture里写的<%= Devise::Encryptor.digest(Traveler, 'password') %>,首先得确认Traveler模型确实是绑定Devise的用户模型,而且已经在模型里加上了:database_authenticatable模块。要是模型名写错或者漏加了这个模块,生成的加密密码就和实际登录时计算的不匹配,自然会被拒绝。验证测试请求的参数格式
Devise的登录接口对参数格式有要求,集成测试里发送请求时,参数得嵌套在对应模型名的键下。比如你的模型是Traveler,请求应该这么写:post traveler_session_path, params: { traveler: { email: 'example@email.com', password: 'password' } }要是参数没嵌套,Devise识别不到账号密码,直接就返回401了。
处理CSRF Token的问题
集成测试里Rails通常会自动处理CSRF,但如果是直接发POST请求而不是通过表单提交,可能得手动带上CSRF token。你可以先访问登录页拿到token,再放到请求头里:get new_traveler_session_path post traveler_session_path, params: { traveler: { email: 'example@email.com', password: 'password' } }, headers: { 'X-CSRF-Token': response.headers['X-CSRF-Token'] }确认用户状态是否有效
Fixture里的confirmed_at和confirmation_sent_at是2016年的时间,虽然理论上没问题,但可以试试换成当前时间(比如<%= Time.now %>),确保用户处于已确认的活跃状态,避免某些时间相关的验证逻辑悄悄拦了登录请求。试试Devise的测试辅助方法
Devise本身提供了测试用的sign_in辅助方法,你可以直接在测试里调用它来模拟登录,这样能快速排查是请求的问题还是配置的问题:sign_in travelers(:one)用这个方法后如果能正常访问需要授权的页面,那就说明之前的手动登录请求有问题,反之就是用户模型或者Fixture的配置有问题。
内容的提问来源于stack exchange,提问作者Arthur

