Rspec login_user 问题

Rspec login_user issue

我在使用 Devise/Rspec 登录用户以点击测试路线时遇到问题。我按照设计概述使用了 support/controller_macros 模块,但每当我尝试使用 login_user 在我测试的任何部分我都收到错误:before is not available from within an example (e.g. an it block) or from constructs that run in the scope of an example (e.g. before, let, etc). It is only available on an example group (e.g. a describe or context block).

我试过四处移动,确保我的所有需求都设置正确,等等。

我的测试:

require "rails_helper"

RSpec.describe BallotsController, type: :controller do
  describe "index" do
    it "renders" do
      login_user
      ballots_path
      expect(response).to be_success
      expect(response).to render_template("index")
    end
  end
end

(我试过在 describe 块和上面的块中添加 login_user)

我的controller_macros:

  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user_confirmed]
      user = FactoryBot.create(:user_confirmed)
      sign_in user
    end
  end

  def login_admin
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:admin]
      user = FactoryBot.create(:admin)
      sign_in user
    end
  end
end

我的规格助手:

require "rails_helper"
require_relative "support/controller_macros"
RSpec.configure do |config|
  # rspec-expectations config goes here. You can use an alternate
  # assertion/expectation library such as wrong or the stdlib/minitest
  # assertions if you prefer.
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end

  config.shared_context_metadata_behavior = :apply_to_host_groups
  config.include ControllerMacros, :type => :controller
  config.include Devise::Test::ControllerHelpers, :type => :controller

  config.example_status_persistence_file_path = "spec/examples.txt"

  config.disable_monkey_patching!

  if config.files_to_run.one?
    config.default_formatter = "doc"
  end

  config.profile_examples = 10

  config.order = :random

  Kernel.srand config.seed
end

我希望它能让用户登录,并让控制器正确命中索引路由。谢谢!

代码中唯一的问题(解决错误,而不深入讨论是否应该使用此方法)是您在 it 块中有登录用户,这不能是因为它正在调用 before(:each).

如果您看到 device documentation,您还会看到它在 it 块中没有此调用,而是在 it 块之外的 describe 块中。它将此调用应用于该描述块中的所有 it 块。

您的代码将变为:

RSpec.describe BallotsController, type: :controller do
  describe "index" do
    login_user
    it "renders" do
      ballots_path
      expect(response).to be_success
      expect(response).to render_template("index")
    end
  end
end

我喜欢的方式:

在您的 controller_macros 中,将 login_user 替换为:

def login_user(user)
  @request.env["devise.mapping"] = Devise.mappings[:user_confirmed]
  sign_in user
end

现在,无论您想在哪里登录用户,您都可以这样做:

RSpec.describe BallotsController, type: :controller do
  describe "index" do
    let(:user) { FactoryBot.create(:user) }

    it "renders" do
      login_user(user)
      ballots_path
      expect(response).to be_success
      expect(response).to render_template("index")
    end
  end

  # OR

  describe "index" do
    let(:user) { FactoryBot.create(:user) }

    before(:each) do
      login_user(user)
    end

    it "renders" do
      ballots_path
      expect(response).to be_success
      expect(response).to render_template("index")
    end
  end
end