RSpec в Rails: как пропустить файл before_filter?
Я пытаюсь проверить свой контроллер и поддерживать разделение проблем.
Первой проблемой является "Кто может выполнить какое действие?"
Я использую authlogic для аутентификации и be9 acl9 для авторизации. Но это не имеет значения, все мои вопросы авторизации обрабатываются в before_filter
. Я тестирую такой before_filter
чем-то похожим на это:
describe SomeModelsController, "GET to index (authorization)" do
before(:each) do
@siteadmin = mock_model(User)
@siteadmin.stub!(:has_role?).with("siteadmin", nil).and_return(true)
end
it "should grant access to a siteadmin" do
controller.should_receive(:current_user).at_least(:once).and_return(@siteadmin)
get :index
response.should be_success
end
end
Эта спецификация работает отлично!
Теперь второе беспокойство: "Делает ли действие то, что он должен делать?"
Это не требует проверки авторизации. Лучшее/чистое решение будет пропускать, что before_filter
все вместе и просто сделать что-то вроде:
describe SomeModelsController, "GET to index (functional)" do
it "should find all Models" do
Model.should_receive(:find).with(:all)
end
end
Не нужно беспокоиться о том, какой пользователь должен выполнить первую роль. Прямо сейчас я решил это так:
describe SomeModelsController, "GET to index (functional)" do
before(:each) do
@siteadmin = mock_model(User)
@siteadmin.stub!(:has_role?).with("siteadmin", nil).and_return(true)
controller.stub!(:current_user).and_return(@siteadmin)
end
it "should find all Models" do
Model.should_receive(:find).with(:all)
end
end
Если я теперь решил, что мой сайт-админ не имеет права доступа к действию индекса больше, он не только сломает один spec, а именно спецификацию, которая должна сломаться в таком случае, - но и полностью несвязанная вторая спецификация.
Я знаю, что это в основном незначительная проблема, но было бы неплохо, если бы кто-нибудь мог придумать (элегантное) решение!
Ответы
Ответ 1
Чтобы пропустить фильтр до:
controller.class.skip_before_filter :name_of_method_used_as_before_filter
Единственное предостережение (упомянутое в документах) заключается в том, что это будет работать только для фильтров ссылок на методы, а не для procs.
В качестве альтернативы вы можете заглушить current_user.has_role?
describe SomeModelsController, "GET to index (functional)" do
before(:each) do
controller.current_user.stub!(:has_role?).and_return(true)
end
it "should find all Models" do
Model.should_receive(:find).with(:all)
end
end
Ответ 2
Старый вопрос, но я должен был решить это совсем недавно. Это будет работать только для Rails 3.1, для более ранних версий вы должны заменить _process_action_callbacks
на filter_chain
(untested)
Вы можете просто удалить подходящий Proc из цепочки фильтров (пример: Unit: Unit):
class RandomControllerTest < ActionController::TestCase
def setup
@controller.class._process_action_callbacks.each do |f|
@controller.class._process_action_callbacks.delete(f) if f.raw_filter.to_s.match(/**<match for your proc>**/)
end
end
end
Ответ 3
Как просто не делать запрос GET?
Попробуйте вызвать метод контроллера самостоятельно.
controller.index