我知道这个问题是asked before中的various forms。
但是,我正在努力解决似乎无法在这些答案中解决的问题。我登录的用户不在规范内。
您应该如何在请求规范中复制身份验证/登录的用户?
这是我尝试过的事情,也是我正在做的事情。 我正在使用Auth0作为身份验证处理程序。我有一个在Auth0回调中调用的登录方法,因此我为自己的测试拼凑了一个模拟_认证端点,以利用资源对象。
这是我当前的设置,也是我尝试复制登录流程时所做的工作。
#/spec/requests/api/v1/account_spec.rb
RSpec.describe "API V1 Accounts", type: :request do
# Factories.
...
describe "PATCH update" do
subject(:http_request) { patch endpoint, params: { account: account_params, format: :json } }
# set some defaults
let(:id) { account.id }
let(:endpoint) { "/api/v1/accounts/#{id}" }
let(:account_params) { {} }
# Configure subdomain contstraint
within_subdomain :api do
before do |example|
mock_login(resource) unless example.metadata[:skip_signin]
http_request
end
context "when no resource is logged in", :skip_signin do
# This spec passes fine, as it's skipping login.
it_behaves_like "an unauthenticated private api request"
end
context "when there is no record to be found" do
let(:id) { SecureRandom.uuid }
let(:resource) { create(:user) }
it "fails to access a record" do
expect(response).to have_http_status(:not_found)
end
end
xcontext "when the user has access permission" do
end
end
end
end
-
# config/routes.rb
post "/auth/mock/:id", to: "auth#mock", as: :mock_login if Rails.env.test?
-
# auth_controller.rb
def mock
return unless Rails.env.test?
@resource = User.find_by(params[:id]
signin(@resource)
end
def signin(resource)
reset_session
create_session(resource)
after_signin_redirect_for(resource)
end
我正在使用此帮助程序从我的请求规范中调用它
module Helpers
module Auth
def mock_login(resource)
post mock_login_path(resource.id)
end
end
end
RSpec.configure do |config|
config.include Helpers::Auth, type: :request
end
所以。通过抛出一堆调试器和binding.pry,我可以看到我的嘲笑(resource)已成功调用,并且在signin
方法的末尾,我的助手signed_in?
是true
。成功设置会话。
我现在遇到的问题是,当它在before块或it块中运行时,它并没有保留在功能说明中。
before do |example|
mock_login(resource) unless example.metadata[:skip_signin] # signed_in? == true!
http_request # signed_in? == nil
end
module API
module V1
class AccountsController < APIController
before_action :authenticate_resource!
# ^ This is where the spec is failing to recognise the signed in resource from the mock_login method.
before_action :set_account
# PATCH /api/v1/accounts/:id
def patch_update
# Cancancan Authorization
authorize! :update, @account
# handle patch
...
end
private
def set_account
binding.pry # We're never making it here.
@account = Account.find_by(id: params[:id])
end
...
end
end
end
def authenticate_resource!
return true if signed_in?
respond_to do |format|
format.json { head(:unauthorized) }
end
end
编辑:进行了一些更改,以使我的要求更加清楚。