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

Rails API应用使用devise时无法编写rspec登录请求测试用例如何解决

问题根因

你当前的测试无法通过的核心原因是:Devise提供的sign_in测试辅助方法是测试层直接注入登录态,不会走实际的SessionsController#create登录接口逻辑,自然不会触发devise-jwt的token签发逻辑,也不会生成响应对象,所以你读取的response是空值。

可行解决思路

1. 修正登录接口测试逻辑

如果你的测试目标是验证登录接口本身的返回(token、状态码),不要用sign_in辅助方法,而是模拟真实请求调用登录接口:

context 'When logging in' do
  let(:user) { create(:user, password: 'testpass123') } # 确保factory中密码设置和这里一致

  it 'returns a valid token and 200 status' do
    # 替换为你实际的登录路由,参数结构要符合你接口要求
    post '/users/sign_in', params: {
      user: {
        email: user.email,
        password: 'testpass123'
      }
    }, as: :json

    expect(response.status).to eq(200)
    expect(response.headers['Authorization']).to be_present
    expect(response.headers['Authorization']).to start_with('Bearer ')
  end
end

注意:request类型测试不需要设置request.env["devise.mapping"],该配置仅用于controller单元测试

2. 检查devise-jwt基础配置

如果调用接口后还是没有返回token,确认以下配置是否正确:

  • 检查config/initializers/devise.rb中是否正确配置了jwt相关参数:
    config.jwt do |jwt|
      jwt.secret = Rails.application.credentials.devise_jwt_secret_key
      jwt.dispatch_requests = [
        ['POST', %r{^/users/sign_in$}] # 路径要和你的登录路由完全匹配
      ]
      jwt.revocation_requests = [
        ['DELETE', %r{^/users/sign_out$}]
      ]
    end
    
  • 确认User模型已引入jwt模块:
    class User < ApplicationRecord
      devise :database_authenticatable, :registerable,
             :jwt_authenticatable, jwt_revocation_strategy: JwtDenylist # 按你实际的吊销策略调整
    end
    
  • 确认API模式下已关闭默认导航跳转:config.navigational_formats = [],避免devise尝试跳转HTML页面导致接口返回302

3. 如需测试其他需要登录态的接口

如果你的目标是测试其他需要登录才能访问的接口,不需要验证登录接口本身,有两种实现方式:

  • 用sign_in辅助方法直接注入登录态,不需要处理jwt
  • 若接口强制要求校验jwt请求头,可手动生成token放到请求头:
    let(:user) { create(:user) }
    let(:auth_headers) {
      token = Warden::JWTAuth::UserEncoder.new.call(user, :user, nil).first
      { 'Authorization' => "Bearer #{token}" }
    }
    
    it 'accesses protected route successfully' do
      get '/protected/route', headers: auth_headers, as: :json
      expect(response.status).to eq(200)
    end
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 13:09:03