ruby on rails - tutorial - Rails, Restful Authentication & RSpec: cómo probar nuevos modelos que requieren autenticación
rails api tutorial (4)
Creé una aplicación de aprendizaje con Bort , que es una aplicación base que incluye Restful Authentication y RSpec. Lo tengo en funcionamiento y agregué un nuevo objeto que requiere que los usuarios inicien sesión antes de que puedan hacer algo ( before_filter :login_required
en el controlador). [edit: También debo mencionar que el usuario has_many
de la nueva clase y que solo el usuario debería poder verla.]
Creé el nuevo modelo / controlador utilizando los generadores de Rspec que han creado una serie de pruebas predeterminadas. Todos pasan si no hay before_filter
pero varios fallan, como debería esperarse, una vez que el before_filter
está en su lugar.
¿Cómo puedo hacer que las pruebas generadas se ejecuten como si hubiera / no un usuario conectado? ¿Necesito un lote completo de coincidencias que no haya iniciado sesión - redireccionar las pruebas? Supongo que es una especie de técnica burlona o accesorio, pero soy nuevo en RSpec y un poco a la deriva. También se apreciarán buenos enlaces tutoriales de RSpec.
Tengo una configuración muy similar, y abajo está el código que estoy usando para probar esto. En cada una de las describe
que puse:
it_should_behave_like "login-required object"
def attempt_access; do_post; end
Si todo lo que necesitas es un inicio de sesión, o
it_should_behave_like "ownership-required object"
def login_as_object_owner; login_as @product.user; end
def attempt_access; do_put; end
def successful_ownership_access
response.should redirect_to(product_url(@product))
end
Si necesitas propiedad Obviamente, los métodos de ayuda cambian (muy poco) con cada giro, pero esto hace la mayor parte del trabajo por usted. Esto está en mi spec_helper.rb
shared_examples_for "login-required object" do
it "should not be able to access this without logging in" do
attempt_access
response.should_not be_success
respond_to do |format|
format.html { redirect_to(login_url) }
format.xml { response.status_code.should == 401 }
end
end
end
shared_examples_for "ownership-required object" do
it_should_behave_like "login-required object"
it "should not be able to access this without owning it" do
attempt_access
response.should_not be_success
respond_to do |format|
format.html { response.should be_redirect }
format.xml { response.status_code.should == 401 }
end
end
it "should be able to access this if you own it" do
login_as_object_owner
attempt_access
if respond_to?(:successful_ownership_access)
successful_ownership_access
else
response.should be_success
end
end
end
Encontré algunas respuestas a mi propia pregunta. Básicamente, tenía que entender cómo burlar al usuario de restful_authentication
para que las pruebas de controlador rspec autogeneradas pudieran pasar incluso si había agregado before_filter: login_required
.
Aquí hay algunos de mis recursos recién encontrados:
RSpec: debería comportarse como
rspec, restful_authentication y login_required
utilizando restful_authentication current_user dentro de las especificaciones del controlador
Para simular que un usuario está conectado, hackeo el controlador para configurar @current_user
manualmente:
module AuthHelper
protected
def login_as(model, id_or_attributes = {})
attributes = id_or_attributes.is_a?(Fixnum) ? {:id => id} : id_or_attributes
@current_user = stub_model(model, attributes)
target = controller rescue template
target.instance_variable_set ''@current_user'', @current_user
if block_given?
yield
target.instance_variable_set ''@current_user'', nil
end
return @current_user
end
def login_as_user(id_or_attributes = {}, &block)
login_as(User, id_or_attributes, &block)
end
end
Cuando no estoy probando la autenticación, pero probando los controladores que necesitan que el usuario sea autenticado, generalmente corto el método de filtro:
before(:each) do
controller.stub!(:authenticate).and_return(true)
end
El ejemplo anterior funciona donde mi before_filter está configurado para el método de autenticación:
before_filter :authenticate
y la autenticación en mi aplicación utiliza Autenticación básica HTTP, pero realmente puede ser cualquier otro mecanismo de autenticación.
private
def authenticate
authenticate_or_request_with_http_basic do |user,password|
user == USER_NAME && password == PASSWORD
end
end
Creo que es una forma bastante directa de probar.