2016-08-24 40 views
8

Próbuję przetestować, czy ktoś może zalogować się do mojej witryny, wysyłając żądanie POST do mojego SessionsController. Widziałem tę drogę polecaną w kilku miejscach:Test szyn - sprawdzanie, czy użytkownik jest zalogowany przy pomocy narzędzia Devise

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 

Ale ten test nie jest poprawny. Wywołanie @controller.current_user podejmie próbę uwierzytelnienia użytkownika przy użyciu opublikowanych parametrów i zwróci user, jeśli podany adres e-mail/hasło są poprawne. Nie ma gwarancji, że akcja create wywołuje w rzeczywistości sign_in lub current_user.

Nawet jeśli ponownie napiszę test, aby sprawdzić, czy te metody są wywoływane, możliwe jest, że można wywołać inne metody, np. sign_out.

Czy istnieje bardziej ostateczny sposób ostatecznego sprawdzenia, czy użytkownik jest zalogowany, a jeśli tak, to kim jest ten użytkownik?

EDIT -

Na przykład, następujący test przejdzie

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 

gdy SessionsController # utworzyć działanie jest:

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

Czy to może pomóc? http://stackoverflow.com/questions/23793597/how-to-access-devise-current-user-in-a-rspec-feature-test – tmn4jq

+0

Obawiam się, że nie sądzę, że to pomaga. Nie mam problemu z wywołaniem current_user. – user1063998

+0

to '.current_user' metoda, która próbuje zalogować użytkownika, lub czy jest to attr_reader dla zmiennej instancji? Jeśli pierwszy, wydaje się, że to, co opisujesz, jest oczekiwanym zachowaniem. –

Odpowiedz

2

rozwiązanie przy minimalnych zmianach proponowanych kod w pytanie:

Musisz zainicjalizować system przed rozpoczęciem testu. Spróbuj poprzedzenie następujący kod przed kodem i t 'must be able to sign in a user' do:

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

ten powinien włączyć test do ważnego testu na kontrolerze pocztowym.

Objaśnienie:

Moje założenie jest, że test powyżej zawsze udaje, ponieważ użytkownik jest już zalogowany (wg innych badań prowadzonych przed tym jednym). Możesz to sprawdzić, używając byebug w linii po it i uruchamiając current_user w konsoli bybug's. Jeśli nie jest to nil, użytkownik jest już zalogowany, co unieważnia test.

Uwaga, że ​​(różny od tego, co jest omówione powyżej w komentarzach), current_user nie zmienia statusu użytkownika; jest to funkcja tylko do odczytu.

Krótszy/czystsze rozwiązanie:

Moim zdaniem, nie ma aa przejrzysty sposób wykonać taki test jak następuje:

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 

ze stwierdzeniem should change from nil to user, sprawdzić, że użytkownik został wylogowany przed rozpoczęciem testu i zalogowany użytkownik, po wykonaniu testu.

uwaga, że ​​część

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

jest równoważna (być może łatwiej zrozumieć) kodu

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

omówionego here.

+0

Dzięki za odpowiedź. Wierzę, że 'current_user' może zaktualizować stan użytkownika. Dodałem przykładowy test w oryginalnym pytaniu, które moim zdaniem ilustruje problem. – user1063998

+0

Po prostu pomyślałam, może jest jakiś wcześniejszy/filtr, który coś robi, ale nie mogę tego teraz sprawdzić. Być może masz rację: – user1063998

+0

@ user1063998: czy miałeś okazję przetestować moją sugestię? Zainwestowałem sporo czasu, aby wymyślić rozwiązanie (przynajmniej myślę, że jest to rozwiązanie). W każdym razie było to dobre ćwiczenie, ale wolałbym, żeby to sprawdził osoba, która poprosiła. – Olli