Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authentication with Devise in Rspec tests

I'm having trouble getting my Rspec tests to run correctly on items where Devise is trying to authenticate a user in a before_filter.

I followed the example from the Devise Git wiki: How To: Controllers and Views tests with Rails 3 (and rspec)

spec/spec_helper.rb:

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'

Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
   config.include Devise::TestHelpers, :type => :controller
   config.extend ControllerMacros, :type => :controller
   config.fixture_path = "#{::Rails.root}/spec/fixtures"
   config.use_transactional_fixtures = true
   config.infer_base_class_for_anonymous_controllers = false
end

spec/support/controller_macros.rb:

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

spec/controllers/test.rb:

require 'spec_helper'
describe ProjectsController do
  def valid_attributes
    {
    :name         => 'Project',
    :description  => 'Description'
    }
  end

  def valid_session
    {}
  end

  describe "Test" do

    login_user

    it "assigns all projects as @projects" do
      # test passes if the following line is here, otherwise fails
      subject.current_user.should_not be_nil

      project = Project.create! valid_attributes
      get :index, {}, valid_session
      assigns(:projects).should eq([project])
    end
  end
end

app/controllers/projects_controller.rb (straight from generator except for addition of a before filter:

class ProjectsController < ApplicationController

  before_filter :authenticate_user!

  # GET /projects
  # GET /projects.json
  def index
    @projects = Project.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @projects }
    end
  end

  # GET /projects/1
  # GET /projects/1.json
  def show
    @project = Project.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @project }
    end
  end

  # GET /projects/new
  # GET /projects/new.json
  def new
    @project = Project.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @project }
    end
  end

  # GET /projects/1/edit
  def edit
    @project = Project.find(params[:id])
  end

  # POST /projects
  # POST /projects.json
  def create
    @project = Project.new(params[:project])

    respond_to do |format|
      if @project.save
        format.html { redirect_to @project, notice: 'Project was successfully created.' }
        format.json { render json: @project, status: :created, location: @project }
      else
        format.html { render action: "new" }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /projects/1
  # PUT /projects/1.json
  def update
    @project = Project.find(params[:id])

    respond_to do |format|
      if @project.update_attributes(params[:project])
        format.html { redirect_to @project, notice: 'Project was successfully updated.' }
        format.json { head :ok }
      else
        format.html { render action: "edit" }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /projects/1
  # DELETE /projects/1.json
  def destroy
    @project = Project.find(params[:id])
    @project.destroy

    respond_to do |format|
      format.html { redirect_to projects_url }
      format.json { head :ok }
    end
  end
end

Why does the test pass with the inclusion of subject.current_user.should_not be_nil but fails when it is not included?

like image 638
y0mbo Avatar asked Jun 12 '12 18:06

y0mbo


1 Answers

I ran into the same problem when following the how-to you mention. The solution is to remove calls to valid_session from each of the requests, since it overrides the session values set by the sign_in helper.

It's actually documented in a code-block in the very same how-to, I missed it too :(

like image 91
lankz Avatar answered Oct 24 '22 17:10

lankz