【问题标题】:How to test Devise Sessions Controller with RSpec如何使用 RSpec 测试设计会话控制器
【发布时间】:2017-10-04 06:27:07
【问题描述】:

我在自己的控制器中覆盖 SessionsController 并尝试使用 RSpec 进行测试。拳头,我设置设计与

@request.env["devise.mapping"] = Devise.mappings[:user]

我的规格:

require 'rails_helper'

需要'authentication_helper'

RSpec.describe Users::SessionsController, type: :controller do 包括 AuthenticationHelper

描述'创建新会话'做

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

结束 结束

我的 SessionsController 只返回 http 401 或 http 200。 当我运行我的规范时,我收到了这个错误:

无方法错误: 未定义的方法authenticate?' for nil:NilClass # /usr/local/bundle/gems/devise-3.5.6/app/controllers/devise_controller.rb:103:inrequire_no_authentication' # ./spec/controllers/users/sessions_controller_spec.rb:16:in block (3 levels) in <top (required)>' # ./spec/rails_helper.rb:45:inblock (3 级) 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:incleaning' # /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:incall' # /usr/local/bundle/gems/database_cleaner-1.6.0/lib/database_cleaner/configuration.rb:87:in cleaning' # ./spec/rails_helper.rb:44:inblock (2 levels) in '

我做错了什么?

【问题讨论】:

    标签: ruby-on-rails ruby rspec devise


    【解决方案1】:

    您知道,Devise 为控制器规范提供了 RSpec 测试助手。但是,在请求规范中,它们将不起作用。

    这是一个请求规范的解决方案,改编自 Devise wiki。我们将简单地使用 Warden 的测试助手——您可能已经为您的 Cucumber 测试加载了它们。

    首先,我们定义 sign_in 和 sign_out 方法。它们的行为就像您从控制器规范中知道的那样:

    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
    

    最后,为请求规范加载该模块:

    RSpec.configure do |config|
        config.include DeviseRequestSpecHelpers, type: :request
    end
    

    完成。您现在可以像这样编写请求规范:

    sign_in create(:user, name: 'John Doe')
    visit root_path
    expect(page).to include('John Doe')
    

    参考:
    https://makandracards.com/makandra/37161-rspec-devise-how-to-sign-in-users-in-request-specs

    【讨论】:

    • 您回答了一个问题,但没有回答这个问题。问题是“我如何测试我的自定义会话控制器?”不是“如何在我的规范中绕过设计身份验证?”。
    【解决方案2】:

    您必须删除 warden.authenticate! 调用,而不仅仅是 current_user 方法。

    登录成功测试用例:

    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
    

    对于失败案例:

    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
    

    这在设计 4.x 中适用于我。在https://github.com/plataformatec/devise/wiki/How-To:-Stub-authentication-in-controller-specs找到这个

    【讨论】:

      【解决方案3】:

      你应该有一个登录助手,例如

      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
      

      如有任何疑问,请随时发表评论

      【讨论】:

      • 没有办法只测试我的会话控制器吗?我正在通过 Ajax 执行登录,这就是为什么我只想测试我的控制器是否正确返回 200 和 401。
      • 我在 Spec 文件中看到他们需要 require 'authentication_helper' ,所以我认为我应该拥有该文件
      • 这不能回答所提出的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多