Rails, Restful Authentication и RSpec — Как тестировать новые модели, требующие аутентификации
-
09-06-2019 - |
Вопрос
Я создал обучающее приложение, используя Борт, которое представляет собой базовое приложение, включающее Restful Authentication и RSpec.Я запустил его и добавил новый объект, который требует, чтобы пользователи вошли в систему, прежде чем они смогут что-либо сделать (before_filter :login_required
в контроллере).[редактировать:Я также должен упомянуть, что пользователь has_many
нового класса, и только пользователь должен иметь возможность его видеть.]
Я создал новую модель/контроллер, используя генераторы Rspec, которые создали ряд тестов по умолчанию.Они все проходят, если нет before_filter
но некоторые терпят неудачу, как и следовало ожидать, как только before_filter
на месте.
Как мне заставить сгенерированные тесты запускаться так, как будто есть или нет вошедшего в систему пользователя?Нужна ли мне целая партия сопоставлений, не вошедших в систему - тесты перенаправления?Я предполагаю, что это своего рода метод насмешки или приспособления, но я новичок в RSpec и немного сбиваюсь с толку.Также будем признательны за хорошие ссылки на учебные пособия по RSpec.
Решение
У меня очень похожая установка, и ниже приведен код, который я сейчас использую для тестирования этого материала.В каждом из describe
Я вставил:
it_should_behave_like "login-required object"
def attempt_access; do_post; end
Если все, что вам нужно, это логин или
it_should_behave_like "ownership-required object"
def login_as_object_owner; login_as @product.user; end
def attempt_access; do_put; end
def successful_ownership_access
response.should redirect_to(product_url(@product))
end
Если вам нужна собственность.Очевидно, что вспомогательные методы меняются (очень незначительно) с каждым поворотом, но большую часть работы они делают за вас.Это в моем spec_helper.rb
shared_examples_for "login-required object" do
it "should not be able to access this without logging in" do
attempt_access
response.should_not be_success
respond_to do |format|
format.html { redirect_to(login_url) }
format.xml { response.status_code.should == 401 }
end
end
end
shared_examples_for "ownership-required object" do
it_should_behave_like "login-required object"
it "should not be able to access this without owning it" do
attempt_access
response.should_not be_success
respond_to do |format|
format.html { response.should be_redirect }
format.xml { response.status_code.should == 401 }
end
end
it "should be able to access this if you own it" do
login_as_object_owner
attempt_access
if respond_to?(:successful_ownership_access)
successful_ownership_access
else
response.should be_success
end
end
end
Другие советы
Когда я не тестирую аутентификацию, а тестирую контроллеры, которым требуется аутентификация пользователя, я обычно заглушаю метод фильтра:
before(:each) do
controller.stub!(:authenticate).and_return(true)
end
Приведенный выше пример работает, когда для моего before_filter установлен метод аутентификации:
before_filter :authenticate
и аутентификация в моем приложении использует базовую аутентификацию HTTP, но на самом деле это может быть любой другой механизм аутентификации.
private
def authenticate
authenticate_or_request_with_http_basic do |user,password|
user == USER_NAME && password == PASSWORD
end
end
Я думаю, что это довольно простой способ проверить.
Я нашел несколько ответов на свой вопрос.По сути, мне нужно было понять, как высмеивать пользователя из restful_authentication
чтобы автоматически сгенерированные тесты контроллера rspec могли пройти, даже если я добавил before_filter: login_required
.
Вот некоторые из моих только что найденных ресурсов:
РСпец:Он должен вести себя как
rspec, restful_authentication и login_required
использование restful_authentication current_user внутри спецификаций контроллера
Чтобы высмеять пользователя, входящего в систему, я взломал контроллер, чтобы установить @current_user
вручную:
module AuthHelper
protected
def login_as(model, id_or_attributes = {})
attributes = id_or_attributes.is_a?(Fixnum) ? {:id => id} : id_or_attributes
@current_user = stub_model(model, attributes)
target = controller rescue template
target.instance_variable_set '@current_user', @current_user
if block_given?
yield
target.instance_variable_set '@current_user', nil
end
return @current_user
end
def login_as_user(id_or_attributes = {}, &block)
login_as(User, id_or_attributes, &block)
end
end