2011-02-16 11 views
19

yo estaba tratando de probar una vista simple índice, que ha siguiente código en el interior:vistas de pruebas que utilizan CanCan y diseñar con RSpec

- if can? :destroy, MyModel 
    %th Options 

MyModelsController tiene las siguientes opciones (Recursos heredados + CanCan + Idear):

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 

Cuando se ejecuta especificaciones, se estrella en la línea de - if can? :destroy, MyModel

Failure/Error: render 
    ActionView::Template::Error: 
     undefined method `authenticate' for nil:NilClass 

No hay rastreo, nada en que basar ...

Pensé que tal vez no estoy autorizado y firmado al probar vistas, pero Devise::TestHelpers solo debe incluirse en las pruebas del controlador (y así es como lo tengo).

¿Estaba tratando de anular el método? tanto en Ability como en el controlador, pero eso no dio ningún efecto.

Respuesta

28

Esto se describe en el CanCan docs for controller testing, y también se puede modificar para aplicar para ver las especificaciones. He aquí una manera de hacerlo:

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 
+0

no sé cómo me lo perdí, pero funciona perfectamente, gracias! – farnoy

+0

También tuve que colgar 'view.current_ability' así como en' controller' pero esto fue perfecto – Gareth

+0

bingo !!!!!!!!!! –

5

El 'antes: cada' código publicado por Zetetic no funciona para mí. Mis puntos de vista bork en el "¿puedo? método porque 'current_ability' en la vista devuelve nil. Lo arreglé usando este código 'antes: cada' en su lugar:

@ability = Ability.new(user) 
assign(:current_ability, @ability) 
controller.stub(:current_user, user) 
view.stub(:current_user, user) 

El código anterior simula un inicio de sesión.

4

En su spec_helper:

config.include Devise::TestHelpers, :type => :view 

En su opinión especificación:

controller.stub!(current_user: [some user]) 
view.stub!(current_user: [some user]) 
+0

! Intenté incluir Devise :: TestHelpers,: type =>: controller before PERO todavía tenía un problema. incluyendo ayudantes para ver fijo) – ajahongir

1

El problema con la solución de la wiki CanCan es que requiere un @ability. can ... en cada ejemplo, que no lo hace me siento muy seco

Además, en realidad no resuelve las habilidades en sí mismas, sino el método que devuelve la capacidad del controlador. La habilidad no es un stub y, en consecuencia, se verifican las habilidades.

Si está utilizando Rspec y quieren probar sólo el controlador (y no la de habilidades), así es como código auxiliar a cabo:

before(:each) do 
    ability = mock(:ability).as_null_object 
    controller.stub(:current_ability).and_return(ability) 
end 

Esto funciona porque as_null_object devuelve los valores Truthy para todos los métodos, por lo los métodos de comprobación de habilidad pasan.

2

Para RSpec nueva sintaxis 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 
Cuestiones relacionadas