2

I have two models:

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

  has_many :teams, dependent: :destroy
end

and

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

  validates_presence_of :user
end

I am trying to test my TeamsController using Rspec and factory_girl_rails.

Before I can create a new Team I need an authenticated User.

I created a :user factory:

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

Here are the relevant parts of 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

The test is failing:

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

I don't understand how I need to populate :valid_session so that the test will pass. I thought I'd have to explicitly call an authenticate method but that might not be true. I'm trying to test the Team controller... not User authentication.

Any advice would be much appreciated.

2
  • Can you show where you require the user to be authenticated when creating a team? Did you have a look at this? Commented Sep 16, 2015 at 15:04
  • If you are not using devise you can see my sol'n here: stackoverflow.com/questions/39881504/… Commented Oct 7, 2016 at 17:34

1 Answer 1

2

I'd do this in your 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

Then in your controller spec, (provided you're requiring your rails_helper) you can just to sign_me_in whenever you want to be signed in and not bother about the valid_session:

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

However in your specific case you want to know who you're signed in as, so you can do this:

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

The devise mappings line may not be required in your case, but can't say without inspecting your full app.

Sign up to request clarification or add additional context in comments.

3 Comments

This is great @Yule - thanks! When I run the GET #Index test the way you wrote it I see this failure: gist.github.com/rmangino/12913271b8f44449003d Where does sign_in come from?
Apologies, missed an RSpec config. Edited answer: config.include Devise::TestHelpers, type: :controller in your rails_helper
Devise::TestHelpers is deprecated. Use Devise::Test::ControllerHelpers instead

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.