Тестирование представлений, использующих CanCan и Devise с RSpec
Я пытаюсь тест простой вид индекса, который имеет следующий код:
- if can? :destroy, MyModel
%th Options
MyModelsController
имеет следующие параметры (унаследованные ресурсы + CanCan + Devise):
class MyModelsController < ApplicationController
inherit_resources
nested_belongs_to :mymodel
before_filter :authenticate_user!
load_and_authorize_resource :project
load_and_authorize_resource :mymodel, :through => :project
при запуске спецификаций он падает на линии - if can? :destroy, MyModel
Failure/Error: render
ActionView::Template::Error:
undefined method `authenticate' for nil:NilClass
там нет трассировки, ничего, чтобы основываться на...
Я подумал, что, возможно, я не уполномочен и не подписан при тестировании представлений, но Devise::TestHelpers
должен быть включен только в тесты контроллера (и именно так я иметь его.)
Я пытался переопределить метод? в обоих Ability
и контроллер, но это не дало никаких эффектов.
5 ответов
это описано в документы CanCan для тестирования контроллера, а также может быть изменен, чтобы применить для просмотра спецификаций. Вот один из способов сделать это:
require 'spec_helper'
describe "mymodel/index.html.erb" do
before(:each) do
assign(:my_model,mock_model(MyModel))
@ability = Object.new
@ability.extend(CanCan::Ability)
controller.stub(:current_ability) { @ability }
end
context "authorized user" do
it "can see the table header" do
@ability.can :destroy, MyModel
render
rendered.should have_selector('th:contains("Options")')
end
end
context "unauthorized user" do
it "cannot see the table header" do
render
rendered.should_not have_selector('th:contains("Options")')
end
end
end
код "до :каждый", опубликованный zetetic, не работает для меня. Мои взгляды Борк на может?"метод, потому что "current_ability" в представлении возвращает nil. Я исправил это, используя этот код "before :each" вместо:
@ability = Ability.new(user)
assign(:current_ability, @ability)
controller.stub(:current_user, user)
view.stub(:current_user, user)
приведенный выше код имитирует входа.
в spec_helper:
config.include Devise::TestHelpers, :type => :view
на ваш взгляд spec:
controller.stub!(current_user: [some user])
view.stub!(current_user: [some user])
для нового синтаксиса RSpec 3.0
before(:each) do
assign(:my_model,mock_model(MyModel))
@ability = Object.new.extend(CanCan::Ability)
allow(controller).to receive(:current_ability).and_return(@ability)
end
проблема с решением из Cancan wiki заключается в том, что для этого требуется @ability. can ...
в каждом примере, который не чувствует себя очень сухой.
более того, на самом деле это не заглушает сами способности, а метод, который возвращает способность контроллера. Способность не является заглушкой, и, следовательно, способности проверяются.
Если вы используете Rspec и хотите проверить только контроллер( а не его способности), вот как заглушить его out:
before(:each) do
ability = mock(:ability).as_null_object
controller.stub(:current_ability).and_return(ability)
end
это работает, потому что as_null_object
возвращает истинные значения для всех методов, поэтому методы проверки способности проходят.