Rspec 测试由于重定向到登录页面而失败 (Rails + Devise + Cancancan)

Rspec test fails due to to redirection to a page for loggin in (Rails + Devise + Cancancan)

我正在为 Rails 中的控制器编写测试:

require 'rails_helper'

RSpec.describe GoodsController, type: :controller do
  DatabaseCleaner.clean
  
  user = User.create(password: "12345678")
  user.save!

  describe "GET index" do
    it "renders the index template" do
      sign_in user
      get "index"
      expect(response).to render_template("index")
    end
  end

  DatabaseCleaner.clean
end

GoodsController 有这个 index 我想测试的动作:

def index
  if params[:category_id] == nil
    @goods = Good.all
  else
    @goods = Good.where(category_id: params[:category_id])
  end
end

当我 运行 测试时,我收到此错误:

1) GoodsController GET index renders the index template
     Failure/Error: expect(response).to render_template("index")
       expecting <"index"> but was a redirect to <http://test.host/users/sign_in>
     # ./spec/controllers/goods_controller_spec.rb:12:in `block (3 levels) in <top (required)>'

根据 SO 中的其他答案,我添加了 sign_in user 行,但没有帮助。它仍然重定向到日志页面。我该如何解决?

您创建的 user 在 运行 示例(又称测试)时 rspec 不使用。它只是块中的一个变量,没有任何用处。

在处理 fixtures/factories 时,您应该在 beforelet 中或在测试本身(it 块)中创建它们。

 describe "GET index" do
  let(:user) { User.create(password: "12345678") }

  it "renders the index template" do
    # OR, create it here before sign_in
    sign_in user
    get "index"
    expect(response).to render_template("index")
  end
 end

不确定您是否在使用 factory_bot, but you should look at it. Usually DatabaseCleaner is set up inside rails_helper, check this SO post 了解更多详情。

如果您要进行多个需要用户登录的测试,您还可以将 sign_in 包装在 before 钩子中。

describe "GET index" do
  let(:user) { User.create(password: "12345678") }
  
  before do
    sign_in user
  end

  it "renders the index template" do
    get "index"
    expect(response).to render_template("index")
  end
 end