【问题标题】:rspec + Devise: current_user is nil in testsrspec + 设计:current_user 在测试中为零
【发布时间】:2015-11-28 04:58:40
【问题描述】:

我将 Devise 用于我的用户登录和东西,并使用 rspec 进行测试。我已经查看了 rspec 的设计测试指南,并将 ControllerMicros 混合到控制器规格中。 如果我有这样组织的测试,实际上一切都很好:

  describe 'GET #index' do
    context 'user logged in but not admin' do
      login_user
      it 'should redirect to root_path for non_user' do
        get :index
        // I have asserted that the current_user here is not nil
        expect(response).to redirect_to(root_path)
      end
    end
  end

但是,如果我在上下文中有 2 个测试并且我得到 current_user is nil 用于非第一个测试。

  describe 'GET #index' do
    context 'user logged in but not admin' do
      login_user
      it 'should redirect to root_path for non_user' do
        get :index
        // I have asserted that the current_user here is not nil
        expect(response).to redirect_to(root_path)
      end

      it 'should do some other thing' do
        get :index
        // the current_user method returns nil here
        expect(response).to redirect_to(root_path)
      end
    end
  end

最糟糕的是,这个问题似乎不是确定性的:发生得有点随机——因为在几次失败的运行之后,套件刚刚通过我的电脑(但在 Travis my build 上仍然失败)

一些附加信息:

ControllerMacro.rb

module ControllerMacros
  def login_admin
    before(:each) do
      # @request.env["devise.mapping"] = Devise.mappings[:user]
      user = User.find_by(email: 'default_admin@controller.spec')
      user ||= FactoryGirl.create(:user, email: 'default_admin@controller.spec', uid: 'default_admin.controller.spec')
      admin = Admin.find_by(user_id: user.id)
      FactoryGirl.create(:admin, user: user) if not admin
      sign_in user
    end
  end

  def login_user(user = nil)
    before(:each) do
      # @request.env["devise.mapping"] = Devise.mappings[:user]
      user ||= User.find_by(email: 'default_user@controller.spec')
      user ||= FactoryGirl.create(:user, email: 'default_user@controller.spec', uid: 'default_user.controller.spec')
      sign_in user
    end
  end
end

rails_helper.rb

RSpec.configure do |config|
  # for loading devise in test
  config.include Devise::TestHelpers, :type => :controller
  config.extend ControllerMacros, :type => :controller
end

【问题讨论】:

    标签: ruby-on-rails ruby rspec devise


    【解决方案1】:

    您的 login_user 方法在测试套件加载时运行,您应该将它放在 before :each 块中,以便为每个测试运行一次。

    describe "GET index" do 
      before do
        login_user
      end
      it 'blabla' do
        get :index
        expect(response).to redirect_to(root_path)
      end
    end
    

    PS : 不知道你在 login_user 方法中做了什么,但 Devise 有一些不错的助手,你可以包括如下

    #rails_helper.rb
    RSpec.configure do |config|
      config.include Devise::TestHelpers, type: :controller
    end
    
    #then in you test 
    before do
      sign_in user_instance
    end
    

    评论更新

    如果您有多种类型的用户/设计登录条目,则可以尝试指定您尝试登录用户的设计映射,如下所示:

    sign_in :user, user_instance
    sign_in :admin, admin_user_instance      
    

    【讨论】:

    • 我已经在微博中指定了之前(每个)。这不就行了吗?
    • 应该像你一样工作,更新我的答案也许试试我提供的 alt 语法。如果您想要我的意见,但是您的 ControllerMacro 方法做的事情太多,您可能希望用户设计 let 并将您的 let / before 块嵌套在不同的“上下文”块中以实现不同的测试用例
    • 您在谈论哪个 Devise/RSpec 版本?因为在 Devise 4.20 中 Devise::TestHelpers 已弃用,但包含仅适用于 ActionController::TestCase 但不适用于 RSpec 的 Devise::Test::ControllerHelpers ?
    • 请将此答案设置为正确。完成 Devise::TestHelpers 包括:)
    猜你喜欢
    • 2014-07-10
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多