Rails, Restful Authentication & RSpec - Как протестировать новые модели, требующие аутентификации
Я создал обучающее приложение, используя Bort, которое является базовым приложением, которое включает в себя Restful Authentication и RSpec. Я запустил и запустил новый объект, который требует, чтобы пользователи вошли в систему, прежде чем они смогут что-либо сделать (before_filter :login_required
в контроллере). [edit: Я должен также упомянуть, что пользователь has_many
нового класса и только пользователь должен его видеть.]
Я создал новую модель/контроллер с помощью генераторов Rspec, которые создали ряд тестов по умолчанию. Все они передаются, если нет before_filter
, но несколько сбой, как и следовало ожидать, после того, как before_filter
находится на месте.
Как получить сгенерированные тесты для запуска, как если бы пользователь/не был зарегистрированным пользователем? Нужна ли мне целая серия совпадений, не входящих в систему - тесты перенаправления? Я предполагаю, что это какая-то насмешка или техника крепления, но я новичок в RSpec и немного блуждаю. Хорошие ссылки на интерфейс RSpec также будут оценены.
Ответы
Ответ 1
У меня очень похожая настройка, и ниже приведен код, который я использую для проверки этого материала. В каждом из 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
Ответ 2
Если вы не тестируете аутентификацию, а проверяете контроллеры, которым требуется аутентификация пользователя, я обычно блокирую метод фильтра:
before(:each) do
controller.stub!(:authenticate).and_return(true)
end
В приведенном выше примере работает, где my 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
Я думаю, что это довольно простой способ проверить.
Ответ 3
Я нашел несколько ответов на свой вопрос. В принципе, мне нужно было понять, как издеваться над пользователем из restful_authentication
, чтобы тесты автогенерированного rspec-контроллера могли пройти, хотя я добавил before_filter: login_required
.
Вот несколько моих только что найденных ресурсов:
RSpec: он должен вести себя как
rspec, restful_authentication и login_required
используя restful_authentication current_user внутри спецификации контроллера
DRYing вашего контроллера CRUD RSpecs
Ответ 4
Чтобы высмеять пользователя, входящего в систему, я взламываю контроллер, чтобы установить @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