Настройка Warden для использования в спецификациях контроллера RSpec
я смог использовать Devise sign_in
метод входа пользователя в мои спецификации контроллера. Но теперь, когда я удаляю Devise из своего приложения, я не совсем уверен, как получить аналогичную функциональность, работая с just Warden самостоятельно.
как я должен идти о создании spec/spec_helper.rb
и связанной с spec/support/*.rb
файлы, чтобы получить Warden работает в спецификации контроллера достаточно?
Я попытался настроить файл в spec/support/warden.rb
С этими содержание:
RSpec.configure do |config|
config.include Warden::Test::Helpers
config.after do
Warden.test_reset!
end
end
тогда у меня есть before
вызовы, подобные этому, для аутентификации user
фабрика:
before { login_as FactoryGirl.create(:user) }
но вот ошибка, которую я продолжаю видеть:
NameError:
undefined method `user' for nil:NilClass
эта ошибка восходит к my authenticate_user!
метод в контроллере:
def authenticate_user!
redirect_to login_path, notice: "You need to sign in or sign up before continuing." if env['warden'].user.nil?
end
Я был бы признателен за любые рекомендации, которые кто-либо может предоставить.
2 ответов
там основная проблема с тем, что вы пытаетесь сделать. Warden-промежуточное программное обеспечение стойки, но спецификации контроллера RSpec даже не включают стойку, поскольку эти типы спецификаций не предназначены для запуска полного стека приложений, а только кода контроллера. Вы можете протестировать промежуточное ПО с помощью отдельных тестов только для них, но в этом случае я не думаю, что имеет смысл проверять, что сам Warden работает.
чтобы проверить правильность настройки Warden, следует использовать спецификации запроса или спецификации интеграции (огурец, капибара или подобное).
хотя технически возможно издеваться над надзирателем в спецификациях контроллера, я думаю, что это не дает вам большой пользы, значительно увеличивая сложность вашего тестового кода. Имейте в виду, что Rack middleware предназначен для работы в прозрачном виде, так что это легко поменять middleware в и из, как вам нравится. Ваш контроллер не должен напрямую зависеть от Warden (за исключением, возможно,ApplicationController
), на самом деле, так что зависимость от начальника на геймпаде-это признак нарушена инкапсуляция.
я столкнулся с этой же проблемой недавно, поэтому я надеюсь, что этот комментарий будет полезен.
Я не думал, что этот вопрос относится к моей ситуации, но это так:Stubbing Warden на тестах контроллера
как оказалось, Warden не входит в спецификации контроллера RSpec, поэтому вам нужно сделать некоторую магию, чтобы finagle его.
Кэнтаро Имаи ' s контроллер тест помощников для Warden сообщение в блоге было особенно полезным. Вот как я заставил его работать на RSpec.
шаг 1: создать spec/spec_helper/warden.rb
и вставьте в это содержимое, которое Кентаро получил от Devise:
module Warden
# Warden::Test::ControllerHelpers provides a facility to test controllers in isolation
# Most of the code was extracted from Devise's Devise::TestHelpers.
module Test
module ControllerHelpers
def self.included(base)
base.class_eval do
setup :setup_controller_for_warden, :warden if respond_to?(:setup)
end
end
# Override process to consider warden.
def process(*)
# Make sure we always return @response, a la ActionController::TestCase::Behavior#process, even if warden interrupts
_catch_warden {super} || @response
end
# We need to setup the environment variables and the response in the controller
def setup_controller_for_warden
@request.env['action_controller.instance'] = @controller
end
# Quick access to Warden::Proxy.
def warden
@warden ||= begin
manager = Warden::Manager.new(nil, &Rails.application.config.middleware.detect{|m| m.name == 'Warden::Manager'}.block)
@request.env['warden'] = Warden::Proxy.new(@request.env, manager)
end
end
protected
# Catch warden continuations and handle like the middleware would.
# Returns nil when interrupted, otherwise the normal result of the block.
def _catch_warden(&block)
result = catch(:warden, &block)
if result.is_a?(Hash) && !warden.custom_failure? && !@controller.send(:performed?)
result[:action] ||= :unauthenticated
env = @controller.request.env
env['PATH_INFO'] = "/#{result[:action]}"
env['warden.options'] = result
Warden::Manager._run_callbacks(:before_failure, env, result)
status, headers, body = warden.config[:failure_app].call(env).to_a
@controller.send :render, :status => status, :text => body,
:content_type => headers['Content-Type'], :location => headers['Location']
nil
else
result
end
end
end
end
end
Шаг 2: на spec/spec_helper.rb
внутри RSpec.configure
заблокировать, добавьте эту строку, чтобы включить новый модуль:
config.include Warden::Test::ControllerHelpers, type: :controller
Шаг 3: при входе в before
блок, используйте следующий синтаксис:
before { warden.set_user FactoryGirl.create(:user) }
Шаг 4: убедитесь, что вы ссылка request.env['warden']
в контроллерах, а не env['warden']
. Последний не будет работа в спецификациях контроллера в test
окружающая среда.
наконечник шляпы Кентаро Имаи, которому я должен пиво один день (или в другой жизни)!