如何测试 RSpec 中 current_user 的评论?

How do I test the comments of the current_user in RSpec?

所以我有一个 User has_many :comments

在我的 Comments#Index 中,我有这个:

  def index
    @comments = current_user.comments
  end

rails_helper.rbRspec.config... 块中,我有这个:

  # Add Config info for Devise
  config.include Devise::TestHelpers, type: :controller

我的 comments_controller_spec.rb 看起来像这样:

  describe 'GET #index' do
    it "populates an array of comments that belong to a user" do
      user = create(:user)
      node = create(:node)
      comment1 = create(:comment, node: node, user: user)
      comment2 = create(:comment, node: node, user: user)
      get :index, { node_id: node  }
      expect(assigns(:comments)).to match_array([comment1, comment2])
    end
    it "renders the :index template"
  end

这是我的 Users.rb 工厂:

FactoryGirl.define do
  factory :user do
    association :family_tree
    first_name { Faker::Name.first_name }
    last_name { Faker::Name.last_name }
    email { Faker::Internet.email }
    password "password123"
    password_confirmation "password123"
    bio { Faker::Lorem.paragraph }
    invitation_relation { Faker::Lorem.word }
    # required if the Devise Confirmable module is used
    confirmed_at Time.now
    gender 1
  end
end

这是我的 Comments 工厂:

FactoryGirl.define do
  factory :comment do
    association :node
    message { Faker::Lorem.sentence }

    factory :invalid_comment do
      message nil
    end
  end
end

这是我现在遇到的错误:

 Failure/Error: get :index, { node_id: node  }
 NoMethodError:
   undefined method `comments' for nil:NilClass

想法?

您需要先登录:

describe 'GET #index' do
  let(:user) { create(:user) }
  let(:node) { create(:node) }
  let(:comment1) { create(:comment, node: node, user: user) }
  let(:comment2) { create(:comment, node: node, user: user) }

  before do
    @request.env["devise.mapping"] = Devise.mappings[:user]
    sign_in user
  end

  it "populates an array of comments that belong to a user" do
    get :index, { node_id: node }
    expect(assigns(:comments)).to match_array [comment1, comment2]
  end
end

您还可以使用以下代码在 spec/support 目录中创建一个模块:

module SpecAuthentication
  def login_user
    @request.env["devise.mapping"] = Devise.mappings[:user]
    @user = FactoryGirl.create :user
    sign_in @user
  end
end

并将其包含在您的 RSpec.configure 区块中:

config.include SpecAuthentication

现在您可以调用规范中的 login_user 方法:

describe 'GET #index' do
  let(:node) { create(:node) }
  let(:comment1) { create(:comment, node: node, user: @user) }
  let(:comment2) { create(:comment, node: node, user: @user) }

  before { login_user }

  it "populates an array of comments that belong to a user" do
    get :index, { node_id: node }
    expect(assigns(:comments)).to match_array [comment1, comment2]
  end
end

更新

除了在 spec/rails_helper.rb 文件的 configure 块中包含模块,您还可以在支持文件 (spec/support/devise.rb) 本身中添加一个 configure 块:

module SpecAuthorization
  ...
end

RSpec.configure do |config|
  config.include SpecAuthorization
end