如何编写带身份验证的 Rspec 控制器测试?

How to write an Rspec controller test with authentication?

我有两个模型:

# app/models/user.rb
class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable

  has_many :teams, dependent: :destroy
end

# app/models/team.rb
class Team < ActiveRecord::Base
  belongs_to :user

  validates_presence_of :user
end

我正在尝试使用 Rspec and factory_girl_rails 测试我的 TeamsController

在创建新团队之前,我需要一个经过身份验证的用户。

我创建了一个:用户工厂:

FactoryGirl.define do
  factory :user do
    first_name   "John"
    last_name    "Doe"
    email        {|n| "email#{n}@email.com" }
    mobile_phone "1235551234"
    company_name "Widgets Inc."
    password     "password"
  end
end

以下是teams_controller_spec.rb的相关部分:

require 'rails_helper'

RSpec.describe TeamsController, type: :controller do

  # This should return the minimal set of values that should be in the session
  # in order to pass any filters (e.g. authentication) defined in
  # TeamsController. Be sure to keep this updated too.
  let(:valid_session) { {} }

  describe "GET #index" do
    it "assigns all teams as @teams" do
      user = FactoryGirl.create(:user)

      team = Team.create!(name: "New Team Name", user: user)

      get :index, {}, valid_session
      expect(assigns(:teams)).to eq([team])
    end
  end
end

测试失败:

1) TeamsController GET #index assigns all teams as @teams
     Failure/Error: get :index, {}, valid_session
     NoMethodError:
       undefined method `authenticate' for nil:NilClass

我不明白我需要如何填充 :valid_session 才能通过测试。我以为我必须显式调用身份验证方法,但事实可能并非如此。我正在尝试测试团队控制器...而不是用户身份验证。

如有任何建议,我们将不胜感激。

我会在你的 rails_helper:

module ControllerMacros    
  def sign_me_in
    before :each do
      @request.env['devise.mapping'] = Devise.mappings[:user]
      @current_user = FactoryGirl.create(:user)
      sign_in :user, @current_user
    end 
  end 
end

Rspec.configure do |config|
    #other rspec stuff
    config.include FactoryGirl::Syntax::Methods
    config.extend ControllerMacros, type: :controller
    config.include Devise::Test::ControllerHelpers, type: :controller
 end

然后在您的控制器规格中,(前提是您需要 rails_helper)您可以随时 sign_me_in 登录,而不用担心 valid_session :

RSpec.describe TeamsController, type: :controller do
  sign_me_in
  #etc...
end

但是在您的特定情况下,您想知道您以谁的身份登录,因此您可以这样做:

RSpec.describe TeamsController, type: :controller do
  describe "GET #index" do
    it "assigns all teams as @teams" do
      user = FactoryGirl.create(:user)
      team = Team.create!(name: "New Team Name", user: user)
      @request.env['devise.mapping'] = Devise.mappings[:user]
      sign_in :user, user
      get :index
      expect(assigns(:teams)).to eq([team])
    end
  end
end

你的情况可能不需要设计映射行,但如果不检查你的完整应用程序就不能说。