无需Devise,如何在测试中创建current_user?
问题描述
我的应用在全局设置了current_user,此前运行正常,但编写测试时出现401未授权错误。
主控制器核心代码:
class ApplicationController < ActionController::API ... def authenticate_action end end
测试代码:
RSpec.describe 'Api::V1::Articles', type: :request do let(:user) { FactoryBot.build_stubbed :user } describe 'POST /create' do context "with valid user params" do let!(:articles_params) { {article:{ name: "art1" } }} it 'creates a new article' do expect { post "/api/v1/posts/1/articles", params: articles_params } .to change(Article, :count).by(1) end end end end
错误信息:
Completed 400 Unauthorized
解决方法
核心问题是测试请求没通过authenticate_action的认证校验,需要在测试中模拟用户的认证状态,以下是几种常用方案:
方案1:模拟token认证(最常用)
如果你的authenticate_action是通过请求头携带token验证用户,直接在测试请求里添加认证头即可:
it 'creates a new article' do # 生成符合你系统规则的认证token,比如从用户模型获取 auth_token = user.auth_token expect { post "/api/v1/posts/1/articles", params: articles_params, headers: { 'Authorization' => "Bearer #{auth_token}" } }.to change(Article, :count).by(1) end
方案2:临时绕过认证(仅用于特定场景)
如果只是想快速验证接口逻辑,可临时存根认证方法跳过校验:
before do allow_any_instance_of(ApplicationController).to receive(:authenticate_action).and_return(true) end it 'creates a new article' do expect { post "/api/v1/posts/1/articles", params: articles_params } .to change(Article, :count).by(1) end
方案3:使用项目封装的登录辅助方法
如果项目里有现成的登录辅助方法(比如login_as),直接调用即可:
before do login_as(user) # 调用项目内设置current_user的辅助方法 end it 'creates a new article' do expect { post "/api/v1/posts/1/articles", params: articles_params } .to change(Article, :count).by(1) end
额外注意点
- 若
build_stubbed创建的用户未持久化到数据库,而认证逻辑需要查询数据库,建议改用create生成真实用户:let(:user) { FactoryBot.create :user } - 确认请求路径中的
posts/1对应的Post记录存在,否则会引发额外错误,可提前创建:let(:post) { FactoryBot.create :post } it 'creates a new article' do expect { post "/api/v1/posts/#{post.id}/articles", params: articles_params, headers: { 'Authorization' => "Bearer #{user.auth_token}" } }.to change(Article, :count).by(1) end
内容的提问来源于stack exchange,提问作者register
相关产品推荐
相关产品推荐

