2011-09-16 21 views
55

Potrzebuję uzyskać odpowiedź z metody current_user w specyfikacji żądania Rspec/capybara. Metoda jest zdefiniowana w ApplicationController i używa metody helper_method. Metoda powinna po prostu zwrócić identyfikator użytkownika. W ramach testu chciałbym, aby ta metoda zawsze zwracała ten sam identyfikator użytkownika.Jak uruchomić procedurę ApplicationController w żądaniu spec

Alternatywnie, mógłbym naprawić mój problem, ustawiając session[:user_id] w specyfikacji (co zwraca current_user) ... ale to też nie działa.

Czy jedno z nich jest możliwe?

Edit:

Oto co mam (. Nie działa on tylko prowadzi normalną metodę 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 

także nie działa:

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

jest 'current_user' metody klasy? Wydaje mi się że nie. Więc zamiast 'ApplicationController.stub (: current_user)' możesz potrzebować 'ApplicationController.any_instance.stub (: current_user)'. – skalee

Odpowiedz

13

Oto kilka przykładów podstawowej formie.

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

W danym przypadku, uważam, że właściwą formą byłoby:

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

Oto pełna przykładów pracy z projektem pracuję na:

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 

Aby wyjaśnić moje pełne Na przykład, w zasadzie to oznacza, że ​​po zgłoszeniu błędu w dowolnym miejscu aplikacji pojawia się komunikat o błędzie, a użytkownik zostaje przekierowany na numer portals_controller#index. n. Możesz użyć tych formularzy do wyodrębniania i zwracania określonych wartości, testowania wystąpienia podnoszonego błędu itp. Istnieje kilka metod dostępnych dla Ciebie.


Aktualizacja (po dodaniu kodu): za mój komentarz, zmień swój kod tak to brzmi:

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

Dzięki za odpowiedź, ale to wygląda jak specyfikacja kontrolera, w przeciwieństwie do specyfikacji żądania. Jestem całkiem nowy w testowaniu, więc mógłbym się mylić :) –

+0

Stub działa jedynie jako zamiennik każdej metody zdefiniowanej w dowolnej klasie. W podanym przykładzie jest to metoda 'current_user' zdefiniowana w' ApplicationController', poprawna? Ta sama podstawowa forma powinna zadziałać, chyba że nie rozumiem twojego pytania. Czy możesz napisać najlepszą formę testu, który napisałeś, nawet jeśli to nie działa? – jefflunt

+0

Tak więc, zakładałem, że twój test był w specyfikacji, która zaczyna się od 'opis ApplicationController', więc moje złe tam. Jeśli tak nie jest, to nadal powinieneś być w stanie wykonać 'ApplicationController.stub (: current_user) .and_return ([twój obiekt/identyfikator użytkownika))' – jefflunt

57

skalee wydaje się warunkiem poprawną odpowiedź w komentarzu.

Jeżeli sposób starasz się odgałęzienie jest metoda instancji (najbardziej prawdopodobne), a nie metoda następnie klasa trzeba użyć:

ApplicationController.any_instance.stub(:current_user)

+25

To nadal działa dla Rspec 3, ale zawiera ostrzeżenie o przestarzałości. Jest to nowa składnia: 'allow_any_instance_of (ApplicationController) .to receive (: current_user).and_return (your_test_user) ' – Sharagoz

+1

Uwielbiam ten cytat -" Korzystanie z tej funkcji jest często zapachem projektu "- z [Dokumentów Rspec] (https://github.com/rspec/rspec-mocks). – brntsllvn

3

To działa na mnie i daje mi zmienną @current_user używać w testach.

mam pomocnika, który wygląda tak:

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 

a potem w moją prośbę specyfikacje, wzywam:

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

Dla każdego, kto akurat trzeba skrótową metody kontrolera aplikacji to ustawia ivar (i został powstrzymany przez niekończące się brawo o tym, dlaczego nie powinieneś tego robić) tutaj jest sposób, który działa, o smaku Rspec około października 2013.

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

to metoda, która nie robi nic, i ustawia sterownik ivar na kontrolerze rspec i udostępnia go do testu jako @ kampania.

+0

Narzędzie do późnego zakończenia niekończącej się masturbacji, ale w samą porę, aby powstrzymać mnie przed wyrzuceniem mojego komputera przez okno. Dzięki! – eggmatters

1

Żadna z podanych odpowiedzi nie zadziałała. Tak jak w oryginalnym poście @ matt-fordam, mam specyfikację żądania, a nie specyfikację kontrolera. Test renderuje widok bez uruchamiania kontrolera.

Postanowiłem to przez stubbing sposób na widoku, jak opisano w tym other SO post

view.stub(:current_user).and_return(etc) 
Powiązane problemy