2011-09-16 9 views
55

Ho bisogno di stubare la risposta di un metodo current_user in una specifica richiesta Rspec/capybara. Il metodo è definito in ApplicationController e utilizza helper_method. Il metodo dovrebbe semplicemente restituire un id utente. All'interno del test, mi piacerebbe che questo metodo restituisse lo stesso ID utente ogni volta.Come interrompere il metodo ApplicationController nella specifica richiesta

In alternativa, ho potuto risolvere il mio problema impostando session[:user_id] nelle specifiche (che è quello che current_user rendimenti) ... ma questo non sembra funzionare.

Sono entrambi possibili?

Edit:

Ecco quello che ho (. Non funziona 'appena eseguito il metodo CURRENT_USER normale).

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 

anche non funziona:

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 
+13

è 'current_user' un metodo di classe? Immagino di no. Quindi invece di 'ApplicationController.stub (: current_user)' potresti aver bisogno di 'ApplicationController.any_instance.stub (: current_user)'. – skalee

risposta

13

Qui ci sono un paio di esempi della forma di base.

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

Nel vostro caso particolare, credo che la forma corretta sarebbe:

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

Ecco un esempio di lavoro completo da un progetto Io lavoro su:

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 

Per spiegare il mio pieno Ad esempio, in pratica ciò che fa è verificare che, quando viene rilevato un errore ActionController::InvalidAuthenticityToken in qualsiasi punto dell'app, venga visualizzato un messaggio flash e l'utente venga reindirizzato all'account portals_controller#index n. È possibile utilizzare questi moduli per eseguire lo stub e restituire valori specifici, testare un'istanza di un determinato errore che viene sollevata, ecc. Sono disponibili diversi metodi .stub(:action_name).and_[do_something_interesting]().


Aggiornamento (dopo aver aggiunto il codice): al mio commento, modificare il codice in modo che si legge:

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 
+0

Grazie per la risposta, ma sembra una specifica del controller, al contrario di una specifica della richiesta. Sono abbastanza nuovo da testare, quindi potrei sbagliarmi :) –

+0

Stub funge solo da sostituto per qualsiasi metodo definito su qualsiasi classe. Nell'esempio che hai dato, è un metodo 'current_user' definito su' ApplicationController', corretto? La stessa forma base dovrebbe funzionare, a meno che non fraintenda la tua domanda. Puoi pubblicare la migliore forma del test che hai scritto, anche se non funziona? – jefflunt

+0

Quindi, stavo dando per scontato che il test fosse all'interno di una specifica che inizia con 'descrivi ApplicationController', quindi il mio male lì. In caso contrario, dovresti comunque essere in grado di eseguire 'ApplicationController.stub (: current_user) .and_return ([il tuo oggetto utente/id])' – jefflunt

57

skalee sembra aver fornito la risposta corretta nel commento.

Se il metodo che si sta cercando di stub è un metodo di istanza (più probabile) e non un metodo di classe quindi è necessario utilizzare:

ApplicationController.any_instance.stub(:current_user)

+25

Questo funziona ancora per Rspec 3 ma fornisce un avviso di deprecazione. Questa è la nuova sintassi: 'allow_any_instance_of (ApplicationController). Per ricevere (: current_user).and_return (your_test_user) ' – Sharagoz

+1

Love this quote -" L'uso di questa funzione è spesso un odore di design "- dai [documenti Rspec] (https://github.com/rspec/rspec-mocks). – brntsllvn

3

Questo funziona per me e mi dà una variabile @current_user da usare nei test.

ho un aiutante che assomiglia a questo:

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 

E poi nella mia richiesta specifiche, mi chiama:

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

Per chiunque altro che succede ad avere bisogno di stub un metodo di controllo di applicazione che fissa un ivar (ed è stato ostacolato da un'infinita masturbazione sul perché non dovresti farlo) ecco un modo che funziona, con il sapore di Rspec circa ottobre 2013.

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

stub il metodo per non eseguire nulla e imposta ivar sull'istanza controller di rspec e lo rende disponibile per il test come @campaign.

+0

Strumento tardivo per terminare la mastodoneria infinita, ma giusto in tempo per impedirmi di gettare il mio computer fuori dalla finestra. Grazie! – eggmatters

1

Nessuna delle risposte fornite ha funzionato per me. Come nel post originale di @ matt-fordam, ho una specifica della richiesta, non una specifica del controller. Il test mostra solo la vista senza avviare un controller.

ho risolto questo spegnendo il metodo sulla vista come descritto in questo other SO post

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