ruby-on-rails - rack_test - ruby on rails selenium
Cómo apilar el método ApplicationController en la especificación de solicitud (6)
Necesito resguardar la respuesta de un método current_user
en una especificación de solicitud Rspec / capybara. El método se define en ApplicationController
y está utilizando helper_method. El método simplemente debe devolver una identificación de usuario. Dentro de la prueba, me gustaría que este método devuelva el mismo ID de usuario cada vez.
Alternativamente, podría solucionar mi problema configurando la session[:user_id]
en la especificación (que es lo que current_user
devuelve) ... pero eso tampoco parece funcionar.
¿Alguno de estos es posible?
Editar:
Esto es lo que tengo (no funciona. Simplemente ejecuta el método normal de usuario actual).
require ''spec_helper''
describe "Login" do
before(:each) do
ApplicationController.stub(:current_user).and_return(User.first)
end
it "logs in" do
visit ''/''
page.should have_content("Hey there user!")
end
end
También no funciona:
require ''spec_helper''
describe "Login" do
before(:each) do
@mock_controller = mock("ApplicationController")
@mock_controller.stub(:current_user).and_return(User.first)
end
it "logs in" do
visit ''/''
page.should have_content("Hey there user!")
end
end
Aquí hay un par de ejemplos de la forma básica.
controller.stub(:action_name).and_raise([some error])
controller.stub(:action_name).and_return([some value])
En su caso particular, creo que la forma correcta sería:
controller.stub(:current_user).and_return([your user object/id])
Aquí hay un ejemplo completo de trabajo de un proyecto en el que trabajo:
describe PortalsController do
it "if an ActionController::InvalidAuthenticityToken is raised the user should be redirected to login" do
controller.stub(:index).and_raise(ActionController::InvalidAuthenticityToken)
get :index
flash[:notice].should eql("Your session has expired.")
response.should redirect_to(portals_path)
end
end
Para explicar mi ejemplo completo, básicamente, lo que hace es verificar que, cuando se ActionController::InvalidAuthenticityToken
error ActionController::InvalidAuthenticityToken
en cualquier lugar de la aplicación, aparece un mensaje flash y el usuario se redirige a la acción portals_controller#index
. Puede usar estos formularios para anular y devolver valores específicos, probar una instancia de un error dado que se está .stub(:action_name).and_[do_something_interesting]()
, etc. Hay varios .stub(:action_name).and_[do_something_interesting]()
disponibles para usted.
Actualización (después de haber agregado su código): según mi comentario, cambie su código para que diga:
require ''spec_helper''
describe "Login" do
before(:each) do
@mock_controller = mock("ApplicationController")
@mock_controller.stub(:current_user).and_return(User.first)
end
it "logs in" do
visit ''/''
page.should have_content("Hey there user!")
end
end
Esto funciona para mí y me da una variable @current_user
para usar en las pruebas.
Tengo un ayudante que se ve así:
def bypass_authentication
current_user = FactoryGirl.create(:user)
ApplicationController.send(:alias_method, :old_current_user, :current_user)
ApplicationController.send(:define_method, :current_user) do
current_user
end
@current_user = current_user
end
def restore_authentication
ApplicationController.send(:alias_method, :current_user, :old_current_user)
end
Y luego en mis especificaciones de solicitud, llamo:
before(:each){bypass_authentication}
after(:each){restore_authentication}
Ninguna de las respuestas proporcionadas funcionó para mí. Como en la publicación original de @ matt-fordam, tengo una especificación de solicitud, no una especificación de controlador. La prueba solo muestra la vista sin iniciar un controlador.
Resolví esto anulando el método en la vista como se describe en esta otra publicación SO
view.stub(:current_user).and_return(etc)
Para Rspec 3+ la nueva API es:
Para una prueba de controlador, agradable y corto:
allow(controller).to receive(:current_user).and_return(@user)
O para todas las instancias de ApplicationController:
allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(@user)
Para cualquier otra persona que necesite un método de control de aplicación que establezca un ivar (y se quedó bloqueado por la interminable masturbación sobre por qué no debería hacer eso), esta es una forma que funciona, con el sabor de Rspec de octubre de 2013.
before(:each) do
campaign = Campaign.create!
ApplicationController.any_instance.stub(:load_campaign_singleton)
controller.instance_eval{@campaign = campaign}
@campaign = campaign
end
corta el método para no hacer nada, y establece el ivar en la instancia del controlador rspec, y lo pone a disposición de la prueba como @campaign.
skalee parece haber proporcionado la respuesta correcta en el comentario.
Si el método que intentas eliminar es un método de instancia (lo más probable) y no un método de clase, entonces necesitas usarlo:
ApplicationController.any_instance.stub(:current_user)