【问题标题】:Stub authentication in request specs请求规范中的存根身份验证
【发布时间】:2018-04-24 23:00:33
【问题描述】:

我正在寻找执行this 的方法,但在请求规范中。我需要登录和注销 doubleinstance_double 来设计而不是实际的 ActiveModel/ActiveRecord。

通过使用维基页面中的代码:

module RequestSpecHelpers
    def sign_in(user = double('user'))
      if user.nil?
        allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user})
        allow(controller).to receive(:current_user).and_return(nil)
      else
        allow(request.env['warden']).to receive(:authenticate!).and_return(user)
        allow(controller).to receive(:current_user).and_return(user)
      end
    end
  end

我收到此错误:undefined method 'env' for nil:NilClass

我看到了this questionthis wiki,但是如果我想使用用户的双打,这两个都行不通。我使用的是最后一个,与真实用户一起工作正常,但使用双重它不会登录。

测试:

RSpec.describe 'new shipment', type: :request do
  describe 'authenticated as user' do
    before do
      @user = double(:user, id: 1, email: 'user@gmail.com', password: 'password',
                      id_card: '4163649-1', first_name: 'Jane', last_name: 'Doe')

      sign_in @user
    end
  end
end

如果我包括:

RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :requests
end

我收到此错误:

Failure/Error: @request.env['action_controller.instance'] = @controller

     NoMethodError:
       undefined method `env' for nil:NilClass
     # /root/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/devise-4.3.0/lib/devise/test/controller_helpers.rb:40:in `setup_controller_for_warden'

Frederick Cheung 的问题解答

如果我这样做,login_as 方法不会失败,但它并没有真正让用户登录。因此,当我尝试访问具有 before_action :authenticate_user! 回调的路径时,它会失败。

这是我根据他的回答编写的代码:

require 'rails_helper'

RSpec.describe 'new shipment', type: :request do
  describe 'authenticated as user' do
    include Warden::Test::Helpers

    before(:each) do
      Warden.test_mode!
      #stub more methods as needed by the pages you are testing
      user = instance_double(User, to_key: 1, authenticatable_salt: 'example')
      login_as(user, scope: 'user')
    end

    it 'returns 200 Ok' do
      get new_shipment_path
      expect(response).to have_http_status(:ok)
    end
  end
end

这是运行rspec时的响应:

 1) new shipment authenticated as user returns 200 Ok
     Failure/Error: expect(response).to have_http_status(:ok)
       expected the response to have status code :ok (200) but it was :found (302)
     # ./spec/requests/shipments_requests_spec.rb:41:in `block (3 levels) in <top (required)>'

正如您所见,它不允许我访问它重定向我的路径,这是不允许用户访问路径时的常见行为。

如果我将instance_double 更改为保存在数据库中的真实User,这种方法可以正常工作:

# only changed this line in the before hook
user = User.create(email: 'user@gmail.com', password: 'password',id_card: '4163649-1', first_name: 'Jane', last_name: 'Doe')

结果:

Finished in 3.23 seconds (files took 33.47 seconds to load)
1 example, 0 failures

【问题讨论】:

  • 你能显示你调用它的代码吗?
  • @maxpleaner 刚刚补充了
  • 你在用设计吗?
  • @CdotStrifeVII 是的,我正在使用设计
  • 您是否也在 wiki 页面上添加了 TestHelpers 的包含? ` config.include Devise::TestHelpers, :type => :controller config.include ControllerHelpers, :type => :controller `

标签: ruby-on-rails ruby rspec devise


【解决方案1】:

听起来您使用的是 Devise 3.x(因为 Devise::TestHelpers 在设计 4 中已重命名),Devise::TestHelpers 仅设计用于控制器规格。

如果您可以升级到设计 4,它有单独的帮助器用于请求规范和控制器测试。这只是 Warden provides 的一个非常薄的包装,它隐藏了所有与 env 相关的混乱。

使用 double 时有一些额外的复杂性 - 您需要将各种方法设计出来,您可能没有意识到。

以下对我有用

describe 'example' do
  include Warden::Test::Helpers

  before(:each) do
    Warden.test_mode!
    #stub more methods as needed by the pages you are testing
    user = instance_double(User, to_key: 1, authenticatable_salt: 'example')
    login_as(user, scope: 'user')
  end
end

【讨论】:

  • 我刚刚更新了问题,向您展示了当我使用这种方法时会发生什么
  • 您可能需要存根更多方法,具体取决于您在用户通过身份验证后如何授权他们
  • 我使用的是默认的设计认证
  • 我遇到了 ActionDispatch::Cookies::CookieOverflow: 问题,如果我尝试使用简单的 post 请求登录:post user_login_path,blabla cookie 不会在请求和另一个请求之间保存。有没有人遇到过类似的情况?谢谢!
猜你喜欢
  • 2017-08-09
  • 2021-08-07
  • 2021-01-04
  • 2022-08-22
  • 2021-10-25
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多