[英]How to test Devise Sessions Controller with RSpec
I override SessionsController in my own controller and tried to test with RSpec. 我在自己的控制器中重写了SessionsController,并尝试使用RSpec进行测试。 Fist, I setup devise with
拳头,我用
@request.env["devise.mapping"] = Devise.mappings[:user]
my spec: 我的规格:
require 'rails_helper'
require 'authentication_helper' 需要'authentication_helper'
RSpec.describe Users::SessionsController, type: :controller do include AuthenticationHelper RSpec.describe Users :: SessionsController,类型::controller包含AuthenticationHelper
describe 'create new session' do 描述“创建新会话”
before(:each) do
setup_auth
end
let(:user) {FactoryGirl.create(:user, username: 'john', email: 'john@gmail.com', password: 'pwd1234')}
it 'should return 200 with valid username and password' do
post :create, user: {login: 'john', password: 'pwd1234'}
expect(response).to have_http_status 200
expect(controller.current_user.id).to eq(user.id)
end
end end 结束
my SessionsController just return http 401 or http 200. When I run my spec, I get this error: 我的SessionsController只是返回http 401或http200。运行规范时,出现此错误:
NoMethodError: undefined method authenticate?' for nil:NilClass # /usr/local/bundle/gems/devise-3.5.6/app/controllers/devise_controller.rb:103:in
NoMethodError:未定义的方法进行
authenticate?' for nil:NilClass # /usr/local/bundle/gems/devise-3.5.6/app/controllers/devise_controller.rb:103:in
authenticate?' for nil:NilClass # /usr/local/bundle/gems/devise-3.5.6/app/controllers/devise_controller.rb:103:in
require_no_authentication' # ./spec/controllers/users/sessions_controller_spec.rb:16:in block (3 levels) in <top (required)>' # ./spec/rails_helper.rb:45:in
block (3 levels) in ' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/generic/base.rb:16:in cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/base.rb:98:in
cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/configuration.rb:86:in block (2 levels) in cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/configuration.rb:87:in
call' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/configuration.rb:87:in cleaning' # ./spec/rails_helper.rb:44:in
block (2 levels) in ' authenticate?' for nil:NilClass # /usr/local/bundle/gems/devise-3.5.6/app/controllers/devise_controller.rb:103:in
require_no_authentication'#./spec authenticate?' for nil:NilClass # /usr/local/bundle/gems/devise-3.5.6/app/controllers/devise_controller.rb:103:in
in block (3 levels) in <top (required)>' # ./spec/rails_helper.rb:45:in
(3个级别)#。/ block (3 levels) in <top (required)>' # ./spec/rails_helper.rb:45:in
/local/ block (3 levels) in <top (required)>' # ./spec/rails_helper.rb:45:in
块(3个级别) /generic/base.rb:16:正在cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/base.rb:98:in
##/ usr / local / bundle / gems / database_cleaner-1.6.0 cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/base.rb:98:in
lib cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/base.rb:98:in
database_cleaner cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/base.rb:98:in
base.rb:98:正在cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/base.rb:98:in
##/ usr / local / bundle / gems /database_cleaner-1.6.0/lib/database_cleaner/configuration.rb:86 block (2 levels) in cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/configuration.rb:87:in
usr / local / bundle / gems / database_cleaner-1.6.0 / lib / database_cleaner / configuration.rb block (2 levels) in cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/configuration.rb:87:in
通话中##/ cleaning' # ./spec/rails_helper.rb:44:in
/ local / cleaning' # ./spec/rails_helper.rb:44:in
/ cleaning' # ./spec/rails_helper.rb:44:in
/ cleaning' # ./spec/rails_helper.rb:44:in
/ cleaning' # ./spec/rails_helper.rb:44:in
/ cleaning' # ./spec/rails_helper.rb:44:in
/ cleaning' # ./spec/rails_helper.rb:44:in
block (2 levels) in cleaning' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/configuration.rb:87:in
cleaning' # ./spec/rails_helper.rb:44:in
/ cleaning' # ./spec/rails_helper.rb:44:in
阻止状态(2级)中的“
What am I doing wrong? 我究竟做错了什么?
You know that Devise offers RSpec test helpers for controller specs. 您知道Devise为控制器规格提供了RSpec测试助手。 However, in request specs, they will not work.
但是,在请求规范中,它们将不起作用。
Here is a solution for request specs, adapted from the Devise wiki. 这是根据Devise Wiki改编的针对请求规范的解决方案。 We will simply use Warden's test helpers – you probably already load them for your Cucumber tests.
我们将只使用Warden的测试助手-您可能已经将它们加载到Cucumber测试中。
First, we define sign_in and sign_out methods. 首先,我们定义sign_in和sign_out方法。 These will behave just like those you know from controller specs:
它们的行为就像您从控制器规格中了解到的那样:
module DeviseRequestSpecHelpers
include Warden::Test::Helpers
def sign_in(resource_or_scope, resource = nil)
resource ||= resource_or_scope
scope = Devise::Mapping.find_scope!(resource_or_scope)
login_as(resource, scope: scope)
end
def sign_out(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
logout(scope)
end
end
Finally, load that module for request specs: 最后,加载该模块以获取请求规范:
RSpec.configure do |config|
config.include DeviseRequestSpecHelpers, type: :request
end
Done. 完成。 You can now write request specs like this:
您现在可以编写这样的请求规范:
sign_in create(:user, name: 'John Doe')
visit root_path
expect(page).to include('John Doe')
Reference: 参考:
https://makandracards.com/makandra/37161-rspec-devise-how-to-sign-in-users-in-request-specs https://makandracards.com/makandra/37161-rspec-devise-how-to-sign-in-users-in-request-specs
You have to stub out the warden.authenticate!
您必须存根
warden.authenticate!
进行warden.authenticate!
call, not just the current_user
method. 调用,而不仅仅是
current_user
方法。
For login success test cases: 对于登录成功测试用例:
before(:each) do
# assuming `user` is defined and returns a User instance
allow(request.env['warden']).to receive(:authenticate!).and_return(user)
allow(controller).to receive(:current_user).and_return(user)
end
For failure cases: 对于失败情况:
before(:each) do
allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, scope: :user)
allow(controller).to receive(:current_user).and_return(nil)
end
This works for me in devise 4.x. 这在设计4.x中对我有用。 Found this in https://github.com/plataformatec/devise/wiki/How-To:-Stub-authentication-in-controller-specs
在https://github.com/plataformatec/devise/wiki/How-To:-Stub-authentication-in-controller-specs中找到了
You should have a helper for the sign in, for example 例如,您应该有一个帮助登录的人
module AuthenticationHelpers
module Controller
def sign_in(user)
controller.stub(:current_user).and_return(user)
controller.stub(:user_id).and_return(user.id)
end
end
module Feature
def sign_in(user, options={})
visit "/users/sign_in"
fill_in "Email", with: user.email
fill_in "Password", with: options[:password]
click_button "Log in"
end
end
end
Any concerns, do not hesitate to comment 如有任何疑问,请随时评论
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.