2009-11-20 31 views
17

Estoy tratando de probar mi controlador y mantener la separación de las preocupaciones.RSpec in Rails: cómo omitir un before_filter?

La primera preocupación es "¿Quién puede ejecutar qué acción?"
Estoy usando authlogic para la autenticación y be9's acl9 para la autorización. Pero esto no debería importar, todas mis inquietudes de autorización se manejan en un before_filter. Estoy probando como un before_filter por algo similar a esto:

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 

Esta especificación está trabajando muy bien!

Ahora, la segunda preocupación es "¿La acción hace lo que se supone que debe hacer?"
Esto no implica verificar la autorización. La solución mejor/más limpio estaría faltando a que before_filter todos juntos y simplemente hacer algo como:

describe SomeModelsController, "GET to index (functional)" do 
    it "should find all Models" do 
    Model.should_receive(:find).with(:all) 
    end 
end 

Sin tener que preocuparse por las cuales el usuario con papel wich ha conectado al primero. En este momento me lo resolvió así:

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 

Si ahora decidí que mi siteadmin no tiene derecho a acceder a la acción index más, que no sólo se rompería uno de especificaciones - a saber, la especificación que tiene que romper en tal caso, pero también la segunda especificación no relacionada.

Sé que esto es básicamente un problema menor, pero sería bueno si alguien pudiera encontrar una solución (elegante).

Respuesta

34

Para omitir el filtro antes de:

controller.class.skip_before_filter :name_of_method_used_as_before_filter 

La única advertencia (mentioned the docs) es que esto sólo funcionará para los filtros método de referencia, no procsos.

Como alternativa, puede stub 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

Gracias, no pensé en esto. Si no hay forma de omitir el before_filter, esta podría ser la mejor solución. – sebastiangeiger

+0

Ok, actualicé mi respuesta. Espero que eso sea lo que necesitabas. – Baldu

+0

Bueno, omitiendo el filtro anterior funciona. El único inconveniente es que acl9 instala un filtro lambda sin nombre por defecto, por lo que tengo que forzar la creación de un before_filter con nombre. – sebastiangeiger

-9

¿Qué hay de no hacer una petición GET? Intente llamar al método del controlador por sí mismo.

controller.index 
0

Pregunta anterior, pero tuve que resolver esto recientemente. Esto sólo funcionará para Rails 3.1, para las versiones anteriores se debe reemplazar con _process_action_callbacksfilter_chain (no probado)

Usted puede simplemente eliminar una Proc coincidente de la cadena de filtros como tal (Ejemplo de ensayo Unidad ::):

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