2016-08-24 4 views
8

Ich versuche zu testen, dass sich jemand auf meiner Site anmelden kann, indem er eine POST-Anfrage an meine SessionsController sendet. Ich habe diesen Weg an einigen Stellen empfohlen gesehen:Rails-Test - Überprüfen, ob der Benutzer bei Devise angemeldet ist

it 'must be able to sign in a user' do 
    user = create(:user) 
    post :create, format: :js, user: {email: user.email, password: user.password, remember_me: 0} 
    assert_response :success 
    @controller.current_user.must_equal user 
end 

Aber dieser Test ist nicht korrekt. Der Aufruf von @controller.current_user wird versuchen, den Benutzer mithilfe der angegebenen Parameter zu authentifizieren, und gibt user zurück, wenn die angegebene E-Mail/das richtige Kennwort korrekt ist. Es gibt keine Garantie dafür, dass die Aktion create tatsächlich sign_in oder current_user aufruft.

Auch wenn ich den Test neu schreiben, um zu überprüfen, dass diese Methoden aufgerufen werden, ist es möglich, dass andere Methoden wie z. sign_out.

Gibt es einen definitiveren Weg, um letztendlich zu überprüfen, ob ein Benutzer angemeldet ist, und wenn ja, wer der Benutzer ist?

EDIT -

Zum Beispiel wird der folgende Test besteht

it 'must sign in a user' do 
    @controller.current_user.must_equal nil 
    post :create, format: :js, user: {email: @user.email, password: @user.password, remember_me: 0} 
    assert_response :success 
    @controller.current_user.must_equal @user 
end 

wenn die SessionsController # Aktion zu erstellen ist:

def create 
    respond_to do |format| 
     format.js { 
     render nothing: true, status: 200 
     } 
    end 
end 
+0

Kann es helfen? http://stackoverflow.com/questions/23793597/how-to-access-devise-current-user-in-rspec-feature-test – tmn4jq

+0

Ich fürchte, ich glaube nicht, dass das hilft. Ich habe keine Probleme beim Aufruf von current_user. – user1063998

+0

ist '.current_user' eine Methode, die versucht, den Benutzer einzuloggen, oder ist es ein attr_reader für eine Instanzvariable? Wenn der erste, dann scheint es, was Sie beschreiben, ist das erwartete Verhalten. –

Antwort

2

Lösung mit minimalen Änderungen an vorgeschlagenen Code in dem Frage:

Sie müssen das System vor dem Test initialisieren. Versuchen Sie das Voranstellen folgenden Code vor Ihrer i t 'must be able to sign in a user' do Code:

before (:each) do 
    user = FactoryGirl.create(:user) 
    sign_out user 
end 

Diese Ihren Test in einen gültigen Test für Ihren Beitrag Controller drehen sollte.

Erläuterung:

Meine Vermutung ist, dass Ihr Test oben immer erfolgreich ist, weil der Benutzer bereits angemeldet (weitere Tests vor diesem Lauf). Sie können dies überprüfen, indem Sie byebug in der Zeile nach it verwenden und current_user in bybug's Konsole ausführen. Wenn es nicht nil ist, ist der Benutzer bereits angemeldet, wodurch der Test ungültig wird.

Beachten Sie, dass (anders als oben in den Kommentaren diskutiert) current_user den Status des Benutzers nicht ändert; Es ist eine Nur-Lese-Funktion.

Shorter/sauberere Lösung:

Meiner Meinung nach gibt es aa sauberer Weise einen solchen Test durchzuführen, wie folgt:

def sign_in_via_post(user) 
    post :create, format: :js, user: {email: user.email, password: user.password, remember_me: 0} 
end 

... 

before (:each) do 
    user = FactoryGirl.create(:user) 
    sign_out user 
end 

it 'must be able to sign in a user' do 
    { sign_in_via_post user }.should change { current_user }.from(nil).to(user) 
end 

Mit der should change from nil to user Aussage, Sie überprüfen, dass der Benutzer wurde ausgeloggt, bevor der Test beginnt und der Benutzer angemeldet ist, nachdem der Test ausgeführt wurde.

Hinweis, daß der Teil

{ sign_in_via_post user }.should change { current_user }.from(nil).to(user) 

entspricht dem (vielleicht leichter zu verstehen) -Code

{ sign_in_via_post user }.should change { user_signed_in? }.from(false).to(true) 

wie diskutiert here.

+0

Danke für die Antwort. Ich glaube, dass 'current_user' den Status des Benutzers aktualisieren kann. Ich habe in meiner ursprünglichen Frage einen Beispieltest hinzugefügt, der das Problem veranschaulicht. – user1063998

+0

Ich hatte gerade einen Gedanken, vielleicht gibt es eine before_action/filter, die etwas macht, aber ich kann jetzt nicht überprüfen. Vielleicht haben Sie Recht – user1063998

+0

@ user1063998: Hatten Sie eine Chance, meinen Vorschlag zu testen? Ich habe ziemlich viel Zeit investiert, um die Lösung zu finden (zumindest denke ich, es ist die Lösung). Auf jeden Fall war es eine gute Übung, aber ich würde es vorziehen, es von der Person überprüft zu haben, die gefragt hat. – Olli

Verwandte Themen