Ruby on rails 使用请求规范、实例变量和自定义主键测试Rails

Ruby on rails 使用请求规范、实例变量和自定义主键测试Rails,ruby-on-rails,rspec-rails,Ruby On Rails,Rspec Rails,我正在尝试以API only模式为Rails应用程序编写请求规范。在UsersController中,before_操作使用@uid(主键)设置@user,我正试图在规范中分配它 User.uid是一个自定义主键,User.find()在开发和生产中工作得很好(和其他所有操作一样,我正在尝试学习如何在这里进行测试)。这是我在测试中收到的错误: Failure/Error @user = User.find(@uid) ActiveRecord::RecordNotFound: Couldn'

我正在尝试以API only模式为Rails应用程序编写请求规范。在UsersController中,before_操作使用@uid(主键)设置@user,我正试图在规范中分配它

User.uid是一个自定义主键,User.find()在开发和生产中工作得很好(和其他所有操作一样,我正在尝试学习如何在这里进行测试)。这是我在测试中收到的错误:

Failure/Error @user = User.find(@uid)
 ActiveRecord::RecordNotFound:
 Couldn't find User without an ID
//控制器
模块Api
模块V1
类UsersController
“authorize”是分配@uid的ApplicationController上的一个before操作。 我正在跳过它并尝试将@uid分配给创建的用户的uid。一定有更好的方法来做到这一点

编辑: 我正在使用Ruby 2.7.1和rspec rails gem 4.0.1

正在使用ApplicationController中的方法设置@uid,该方法用作before\u操作。它使用一个库来解码firebase jwt并返回一个包含uid的auth_用户对象

class ApplicationController < ActionController::API
  def authorize
    auth_user = FirebaseIdToken::Signature.verify(params[:idToken])
    @uid = auth_user ? auth_user['user_id'] : nil
    render json: {}, status: 401 if @uid.nil?
  end
end
class ApplicationController

我读过一些帖子,其中说您失去了使用请求规范设置实例变量的能力(在文档中找不到),因为这些类型的规范应该尽可能模拟真实场景。控制器实例变量仅在请求后可用,因此我不确定是否可以从请求规范中分配控制器实例变量。

您在规范中设置
@uid
的方式在控制器中不可用。您需要按如下方式设置实例变量,以便在控制器中访问

controller.instance_variable_set(:@uid, user.uid)

使用这种方法,我得到以下错误:
NameError:'uid'不允许作为
controller.instance\u variable\u set(:@uid,user.uid)
的实例变量名。
错误是
FrozenError:无法修改冻结的NilClass:nil
您使用的是哪个ruby和rspec版本?您还可以提供设置
@uid
的代码段吗?我通过编辑问题回答了您的问题。我很感激你的帮助,但我不确定这是不是真的possible@Meursault您是否尝试过规范的
firebase\u id\u token
Gem中给出的步骤-
controller.instance_variable_set(:@uid, user.uid)
require 'rails_helper'
require 'test_helper'

describe 'get user route' do
  let!(:user) { FactoryBot.create(:user) }
  before :each do
    allow_any_instance_of(ApplicationController).to receive(:authorize).and_return(true)
    controller.instance_variable_set(:@uid, user.uid)
  end
  
  before { get '/api/v1/user' }

  it 'returns status code 200' do
    expect(response).to have_http_status(:success)
  end
end