Devise sign_in 不适用于控制器规格
Devise sign_in does not work in controller specs
看来,那个装置的 sign_in 助手不起作用。
常规登录程序非常有效,通过集成测试和手动填写登录表单进行了测试。两种方法都为 current_user.
提供了正确的值
我想测试用户配置文件的编辑控制器功能和 运行 进入 'not authorized' 问题。这让我想到了当前的规范,我只是想批准实际上没有用户登录,因此,current_user 为零。
我想,我的代码中有一些错误。
你有什么提示可以解决我的问题吗?
我正在使用 Rails 5.2 和 ruby 2.5.0
models/user.rb
class User < ApplicationRecord
enum role: [:registered, :editor, :admin]
after_initialize :set_default_role, if: :new_record?
def set_default_role
self.role ||= :registered
end
# Include default devise modules. Others available are:
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_user!
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :approved])
end
end
controllers/registration_controller.rb
class RegistrationsController < Devise::RegistrationsController
private
def after_inactive_sign_up_path_for(resource)
show_post_register_info_path
end
end
config/route.rb
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'registrations'}
root to: 'welcome#home
get 'show_post_register_info', to: 'static_pages#show_post_register_info'
end
specs/rails_heper.rb
require 'rspec/rails'
require 'devise'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Devise::Test::ControllerHelpers, type: :view
config.include Devise::Test::IntegrationHelpers
config.extend ControllerMacros, type: :controller
...
end
support/controller_macros.rb
module ControllerMacros
def login_user
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryBot.create(:user)
sign_in user
end
end
end
最后,我的 controller_spec:
require 'rails_helper'
RSpec.describe RegistrationsController, type: :controller do
describe 'registrations#update' do
context 'signing in a registered user' do
login_user
it 'should have a current_user' do
expect(subject.current_user).to_not eq(nil)
end
it 'should be signed in' do
expect(subject.user_signed_in?).to be true
end
end
end
end
结果:
1) RegistrationsController registrations#update as a registered user changes the password
Failure/Error: expect(subject.user_signed_in?).to be true
expected true
got false
2) RegistrationsController registrations#update as a registered user should have a current_user
Failure/Error: expect(subject.current_user).to_not eq(nil)
expected: value != nil
got: nil
根据您分享的内容,唯一跳出来的是,当我在控制器规范中使用 Devise 的 sign_in
帮助程序时,我将它包装在 before
块中(或大括号),类似于下面的内容,也类似于 login_in
模块中的内容。也许尝试摆脱 (:each)
。此外,您可以在 login_user
方法中插入 pry 或 byebug,以查看当您 运行 您的控制器规格时该方法是否被命中。
let!(:user) { create(:user) }
context 'user is logged in' do
before { sign_in user }
it 'allows some thing' do
# some expectation....
end
end
在 Specs/support/controller_macros.rb 中我稍微编辑了登录程序:
def login_user
before do
@request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryBot.create(:user)
subject.sign_in user # was sign_in user
end
end
我真的不知道为什么我必须从控制器对象调用 sign_in 方法(controller.sign_in
也可以),但我对此很满意。
也许有人想解释一下,为什么一定是subject.sign_in user
。
看来,那个装置的 sign_in 助手不起作用。
常规登录程序非常有效,通过集成测试和手动填写登录表单进行了测试。两种方法都为 current_user.
提供了正确的值我想测试用户配置文件的编辑控制器功能和 运行 进入 'not authorized' 问题。这让我想到了当前的规范,我只是想批准实际上没有用户登录,因此,current_user 为零。
我想,我的代码中有一些错误。
你有什么提示可以解决我的问题吗?
我正在使用 Rails 5.2 和 ruby 2.5.0
models/user.rb
class User < ApplicationRecord
enum role: [:registered, :editor, :admin]
after_initialize :set_default_role, if: :new_record?
def set_default_role
self.role ||= :registered
end
# Include default devise modules. Others available are:
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_user!
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :approved])
end
end
controllers/registration_controller.rb
class RegistrationsController < Devise::RegistrationsController
private
def after_inactive_sign_up_path_for(resource)
show_post_register_info_path
end
end
config/route.rb
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'registrations'}
root to: 'welcome#home
get 'show_post_register_info', to: 'static_pages#show_post_register_info'
end
specs/rails_heper.rb
require 'rspec/rails'
require 'devise'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Devise::Test::ControllerHelpers, type: :view
config.include Devise::Test::IntegrationHelpers
config.extend ControllerMacros, type: :controller
...
end
support/controller_macros.rb
module ControllerMacros
def login_user
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryBot.create(:user)
sign_in user
end
end
end
最后,我的 controller_spec:
require 'rails_helper'
RSpec.describe RegistrationsController, type: :controller do
describe 'registrations#update' do
context 'signing in a registered user' do
login_user
it 'should have a current_user' do
expect(subject.current_user).to_not eq(nil)
end
it 'should be signed in' do
expect(subject.user_signed_in?).to be true
end
end
end
end
结果:
1) RegistrationsController registrations#update as a registered user changes the password
Failure/Error: expect(subject.user_signed_in?).to be true
expected true
got false
2) RegistrationsController registrations#update as a registered user should have a current_user
Failure/Error: expect(subject.current_user).to_not eq(nil)
expected: value != nil
got: nil
根据您分享的内容,唯一跳出来的是,当我在控制器规范中使用 Devise 的 sign_in
帮助程序时,我将它包装在 before
块中(或大括号),类似于下面的内容,也类似于 login_in
模块中的内容。也许尝试摆脱 (:each)
。此外,您可以在 login_user
方法中插入 pry 或 byebug,以查看当您 运行 您的控制器规格时该方法是否被命中。
let!(:user) { create(:user) }
context 'user is logged in' do
before { sign_in user }
it 'allows some thing' do
# some expectation....
end
end
在 Specs/support/controller_macros.rb 中我稍微编辑了登录程序:
def login_user
before do
@request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryBot.create(:user)
subject.sign_in user # was sign_in user
end
end
我真的不知道为什么我必须从控制器对象调用 sign_in 方法(controller.sign_in
也可以),但我对此很满意。
也许有人想解释一下,为什么一定是subject.sign_in user
。