17

Я пытаюсь проверить свой контроллер и поддерживать разделение проблем.RSpec в Rails: как пропустить файл before_filter?

Первой проблемой является «Кто может выполнить какое действие?»
Я использую authlogic для аутентификации и be9's 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 

Если теперь я решил, что мой SiteAdmin не имеет права доступа к акции индекса больше, было бы не только сломать одну спецификацию, а именно - спецификации, которая должна ворваться такой случай - но и совершенно несвязанный второй спек.

Я знаю, что это в основном незначительная проблема, но было бы неплохо, если бы кто-нибудь мог придумать (изящное) решение!

ответ

34

Для того, чтобы пропустить перед фильтром:

controller.class.skip_before_filter :name_of_method_used_as_before_filter 

Одно предостережение (mentioned the docs) является то, что это будет работать только метод-справочных фильтров, а не 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 
+0

Спасибо, не подумал об этом. Если нет способа пропустить файл before_filter, это может быть лучшим решением. – sebastiangeiger

+0

Хорошо, я обновил свой ответ. Надеюсь, это то, что вам нужно. – Baldu

+0

Ницца, пропуская перед работой фильтр. Единственным недостатком является то, что acl9 устанавливает безымянный лямбда-фильтр по умолчанию, поэтому мне нужно заставить создать имя before_filter. – sebastiangeiger

-9

Как насчет просто не делает запрос GET? Попробуйте вызвать метод контроллера самостоятельно.

controller.index 
0

Старый вопрос, но я должен был решить это совсем недавно. Это будет работать только для Rails 3.1, для более ранних версий вы должны заменить _process_action_callbacks с filter_chain (непроверенных)

Вы можете просто удалить соответствующий Proc из цепочки фильтров, как так (тестовый пример 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 
Смежные вопросы