65 votes

Comment stub ApplicationController méthode de spécification de requête

Je suis besoin de tampon de la réaction d'un current_user méthode dans un Rspec/capybara demande spec. La méthode est définie en ApplicationController et est à l'aide de helper_method. La méthode ne devrait renvoyer un code d'utilisateur. Dans le test, j'aimerais cette méthode pour retourner le même id d'utilisateur à chaque fois.

Sinon, j'ai pu résoudre mon problème en mettant en session[:user_id] dans la spec (qui est ce que l' current_user des retours)... mais cela ne semble pas fonctionner non plus.

L'un de ces possibles?

Edit:

Voici ce que j'ai (il n'est pas de travail. Il fonctionne juste à la normale de la méthode current_user).

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

Aussi ne fonctionne pas:

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

61voto

fess . Points 386

skalee semble avoir fourni la bonne réponse dans les commentaires.

Si la méthode que vous essayez de stub est une méthode d'instance (le plus probable) et non pas une méthode de classe, alors vous devez utiliser:

ApplicationController.any_instance.stub(:current_user)

14voto

jefflunt Points 20244

Voici quelques exemples de la forme de base.

controller.stub(:action_name).and_raise([some error])
controller.stub(:action_name).and_return([some value])

Dans votre cas particulier, je crois que la forme correcte serait:

controller.stub(:current_user).and_return([your user object/id])

Voici un exemple de travail à partir d'un projet que je travaille sur:

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

Pour expliquer mon exemple, en gros ce que ce n'est vérifier que, lorsqu'un ActionController::InvalidAuthenticityToken d'erreur est élevé partout dans l'application, un message flash s'affiche et l'utilisateur est redirigé vers l' portals_controller#index action. Vous pouvez utiliser ces formes de stub et le retour des valeurs spécifiques, le test d'une instance d'une erreur d'être posée, etc. Il y a plusieurs .stub(:action_name).and_[do_something_interesting]() méthodes disponibles pour vous.


Mise à jour (après avoir ajouté votre code): par mon commentaire, modifier votre code afin qu'il lit:

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

3voto

iHiD Points 1746

Cela fonctionne pour moi et me donne un @current_user variable à utiliser dans les tests.

J'ai un assistant qui ressemble à ceci:

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

Et puis, dans ma demande specs, je l'appelle:

before(:each){bypass_authentication}
after(:each){restore_authentication}

2voto

Michael Johnston Points 2195

Pour quelqu'un d'autre qui aurait besoin d'écraser un contrôleur d'application de la méthode qui définit un ivar (et a été entravé par de vastes branlette sur pourquoi vous ne devriez pas le faire), voici une manière qui fonctionne, avec la saveur de Rspec circa octobre 2013.

before(:each) do
  campaign = Campaign.create!
  ApplicationController.any_instance.stub(:load_campaign_singleton)
  controller.instance_eval{@campaign = campaign}
  @campaign = campaign
end

il les talons de la méthode pour ne rien faire, et définit le ivar sur rspec de l'instance du contrôleur, et le rend disponible à l'essai, comme @campagne.

1voto

jwadsack Points 2073

Aucune des réponses a fonctionné pour moi. Comme dans @matt-fordam du post original, j'ai une demande spec, pas un contrôleur de spec. Le test qu'rend l'affichage sans avoir à lancer un contrôleur.

J'ai résolu ce problème en écrasant la méthode sur la vue, comme décrit dans cette autre SORTE de post

view.stub(:current_user).and_return(etc)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X