proyectos ejemplos ruby-on-rails-3 rspec integration-testing stubbing

ruby on rails 3 - ejemplos - Autenticación de copiado en especificación de solicitud



django (5)

Al escribir una especificación de solicitud, ¿cómo se configuran las sesiones y / o los métodos de controlador de stub? Intento anular la autenticación en mis pruebas de integración - rspec / requests

Aquí hay un ejemplo de una prueba

require File.dirname(__FILE__) + ''/../spec_helper'' require File.dirname(__FILE__) + ''/authentication_helpers'' describe "Messages" do include AuthenticationHelpers describe "GET admin/messages" do before(:each) do @current_user = Factory :super_admin login(@current_user) end it "displays received messages" do sender = Factory :jonas direct_message = Message.new(:sender_id => sender.id, :subject => "Message system.", :content => "content", :receiver_ids => [@current_user.id]) direct_message.save get admin_messages_path response.body.should include(direct_message.subject) end end end

El ayudante:

module AuthenticationHelpers def login(user) session[:user_id] = user.id # session is nil #controller.stub!(:current_user).and_return(user) # controller is nil end end

Y el ApplicationController que maneja la autenticación:

class ApplicationController < ActionController::Base protect_from_forgery helper_method :current_user helper_method :logged_in? protected def current_user @current_user ||= User.find(session[:user_id]) if session[:user_id] end def logged_in? !current_user.nil? end end

¿Por qué no es posible acceder a estos recursos?

1) Messages GET admin/messages displays received messages Failure/Error: login(@current_user) NoMethodError: undefined method `session'' for nil:NilClass # ./spec/requests/authentication_helpers.rb:3:in `login'' # ./spec/requests/message_spec.rb:15:in `block (3 levels) in <top (required)>''


Nota para los usuarios de Devise ...

Por cierto, la respuesta de @David Chelimsky puede necesitar un pequeño ajuste si estás usando Devise . Lo que estoy haciendo en mi prueba de integración / solicitudes (gracias a esta publicación de ):

# file: spec/requests_helper.rb def login(user) post_via_redirect user_session_path, ''user[email]'' => user.email, ''user[password]'' => user.password end



FWIW, al trasladar mis pruebas de Test :: Unit a RSpec, quería poder iniciar sesión con varias sesiones (de diseño) en mis especificaciones de solicitud. Me tomó un poco de excavación, pero conseguí que esto funcionara para mí. Usando Rails 3.2.13 y RSpec 2.13.0.

# file: spec/support/devise.rb module RequestHelpers def login(user) ActionController::IntegrationTest.new(self).open_session do |sess| u = users(user) sess.post ''/users/sign_in'', { user: { email: u.email, password: ''password'' } } sess.flash[:alert].should be_nil sess.flash[:notice].should == ''Signed in successfully.'' sess.response.code.should == ''302'' end end end include RequestHelpers

Y...

# spec/request/user_flows.rb require ''spec_helper'' describe ''User flows'' do fixtures :users it ''lets a user do stuff to another user'' do karl = login :karl karl.get ''/users'' karl.response.code.should eq ''200'' karl.xhr :put, "/users/#{users(:bob).id}", id: users(:bob).id, "#{users(:bob).id}-is-funny" => ''true'' karl.response.code.should eq ''200'' User.find(users(:bob).id).should be_funny bob = login :bob expect { bob.get ''/users'' }.to_not raise_exception bob.response.code.should eq ''200'' end end

Editar : error fijo


También podrías cerrar fácilmente la sesión.

controller.session.stub(:[]).with(:user_id).and_return(<whatever user ID>)

Todos los operadores especiales de ruby ​​son de hecho métodos. Llamar a 1+1 es lo mismo que 1.+(1) , lo que significa que + es solo un método. Del mismo modo, la session[:user_id] es lo mismo que llamar al método [] en la session , como session.[](:user_id)


Una especificación de solicitud es una envoltura delgada alrededor de ActionDispatch::IntegrationTest , que no funciona como las especificaciones del controlador (que envuelve ActionController::TestCase ). Aunque hay un método de sesión disponible, no creo que sea compatible (es decir, probablemente esté allí porque un módulo que se incluye para otras utilidades también incluye ese método).

Recomiendo iniciar sesión publicando en cualquier acción que use para autenticar usuarios. Si establece la contraseña ''contraseña'' (por ejemplo) para todas las fábricas del usuario, puede hacer algo como esto:

def login(user) post login_path, :login => user.login, :password => ''password'' end