如何为测试创建current_user ?没有设计



我的应用程序正在为所有应用程序设置current_user,所以在创建测试之前,这是ok的,在主控制器中,我正在设置用户

class ApplicationController < ActionController::API
...
def authenticate_action
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

这取决于您是否也想对每个请求进行验证。如果是这种情况,您需要为该用户设置一个有效的认证头,如下所示:

RSpec.describe 'Api::V1::Articles', type: :request do
let(:user) {  FactoryBot.create :user }
let(:auth_header) { { 'Authorization' => "TOKEN#{user.generate_bearer_token}" } }
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, headers: auth_header
}.to change(Article, :count).by(1)
end
end
end
end

请注意,您需要使用应用程序中的实现更改上述示例的第三行中的"TOKEN#{user.generate_bearer_token}",以便为给定用户生成有效的承载令牌。

您可以决定不关心身份验证是如何实现的,并在测试中模拟整个身份验证逻辑。然后,当然,您必须在其他地方测试身份验证逻辑,以确保实现实际正常工作。

为了模拟实现,我将首先将authenticate_action方法的部分移动到用户模型中的类方法或Auth命名空间中的类中,然后仅调用authenticate_action中的一个方法:

# in app/models/user.rb
def self.find_by_bearer_token(token)
id = Auth::TokenValidator.call(token).result
User.find(id) if id
end
# in your application_controller
def authenticate_action
@user = User.find_by_bearer_token(bearer_token)
render json: 400, status: :unauthorized unless @user
end

使用这样的类方法,在测试中模拟该方法并返回您想要用于规范的任何用户要容易得多:

RSpec.describe 'Api::V1::Articles', type: :request do
let(:user) {  FactoryBot.create :user }

before { allow(User).to receive(:find_by_bearer_token).and_return(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

相关内容

  • 没有找到相关文章

最新更新