Аутентификация с помощью разработки в тестах Rspec
У меня возникают проблемы с тем, чтобы мои тесты Rspec корректно выполнялись в тех элементах, где Devise пытается аутентифицировать пользователя в файле before_filter.
Я следовал примеру из Devise Git wiki: Инструкции по: Контроллерам и представлениям с Rails 3 (и rspec)
спецификации/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
Спецификация/поддержка/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
спецификации/контроллеры/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(прямо из генератора, за исключением добавления фильтра before:
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
Почему тест проходит с включением subject.current_user.should_not be_nil
, но сбой, если он не включен?
Ответы
Ответ 1
Я столкнулся с той же проблемой, следуя о том, как вы упоминаете. Решение состоит в том, чтобы удалить вызовы valid_session
из каждого из запросов, поскольку он переопределяет значения сеанса, заданные помощником sign_in
.
Он фактически задокументирован в кодовом блоке в той же самой инструкции, я тоже пропустил это: (