2011-03-08 170 views
8

我正在嘗試使用rspec,factory_girl & capybara編寫集成測試。我也安裝了黃瓜,但我沒有使用它(據我所知)。使用Rspec和水豚在Rails 3中測試會話

我基本上想要用我的用戶預先填充數據庫,然後進入我的主頁並嘗試登錄。它應該重定向到user_path(@user)。

但是,會話似乎不會在我的/ rspec/requests/integration測試中持久化。

我的規格:/rspec/requests/users_spec.rb

require 'spec_helper' 

describe "User flow" do 

    before(:each) do 
    @user = Factory(:user) 
    end 

    it "should login user" do 

    visit("/index") 

    fill_in :email, :with => @user.email 
    fill_in :password, :with => @user.password 
    click_button "Login" 
    assert current_path == user_path(@user) 
    end 
end 

返回:

Failures: 

    1) User flow should login user 
    Failure/Error: assert current_path == user_path(@user) 
    <false> is not true. 
    # (eval):2:in `send' 
    # (eval):2:in `assert' 
    # ./spec/requests/users_spec.rb:16 

相反,它重定向到我please_login_path - 如果登錄由於某種原因失敗應該發生(或者如果沒有設置會話[:user_id])。

如果我試圖把session.inspect,它作爲一個零對象失敗。

如果我嘗試做這個控制器測試(/rspec/controllers/sessions_spec.rb),我可以沒有問題訪問會話,我可以呼叫會話[:USER_ID]

+1

我不知道這是否相關,但您應該無法通過鍵入@ user.password來獲取用戶的密碼。這是您應用中的安全漏洞。您是否使用純文本存儲密碼? – 2011-03-08 18:20:06

+5

這沒有關係,它可能不是安全漏洞。對#password的調用只會返回一個密碼,因爲它是由Factory在實例變量中設置的。這很可能是他正在使用Devise或類似的東西,它不會以明文形式將密碼屬性保存到數據庫中,因此如果該實例變量消失,它就不可用。 – 2011-03-16 20:27:46

回答

6

如果你是使用Devise,你需要包括Warden :: Test :: Helpers(在spec_helper的要求是個好地方之後),如in the warden wiki所述。

對會話的調用返回nil,因爲作爲集成測試運行時,水豚不提供對它的訪問。

1

你可能已經開始從這個,但我只是在同一個問題掙扎。原來這是一個語法問題。我使用的符號爲:email:password,我應該使用字符串代替("email""password")。

換言之,嘗試改變這一點:

fill_in :email, :with => @user.email 
fill_in :password, :with => @user.password 

這樣:

fill_in "email", :with => @user.email 
fill_in "password", :with => @user.password 
3

我有同樣的問題,雖然填寫表格可能對某些選項,我不得不推出我自己的身份驗證紅寶石,因爲我使用的是第三方認證系統(準確地說,Janrain)....在我的測試中,我結束了使用類似這樣的事情:

這是我的規格/支持/test_helpers_and_stuff.rb

module AuthTestHelper 

    class SessionBackdoorController < ::ApplicationController 
    def create 
     sign_in User.find(params[:user_id]) 
     head :ok 
    end 
    end 

    begin 
    _routes = Rails.application.routes 
    _routes.disable_clear_and_finalize = true 
    _routes.clear! 
    Rails.application.routes_reloader.paths.each{ |path| load(path) } 
    _routes.draw do 
     # here you can add any route you want 
     match "/test_login_backdoor", to: "session_backdoor#create" 
    end 
    ActiveSupport.on_load(:action_controller) { _routes.finalize! } 
    ensure 
    _routes.disable_clear_and_finalize = false 
    end 

    def request_signin_as(user) 
    visit "/test_login_backdoor?user_id=#{user.id}" 
    end 

    def signin_as(user) 
    session[:session_user] = user.id 
    end 

end 
在我的要求規範

然後,水豚和硒,我做了以下內容:

describe "Giveaway Promotion" do 
    context "Story: A fan participates in a giveaway", js: :selenium do 
    context "as a signed in user" do 

     before :each do 
     @user = Factory(:user) 
     request_signin_as @user 
     end 

     it "should be able to participate as an already signed in user" do 
     visit giveaway_path 
     .... 
     end 
    end 
    end 
end 

順便說一句,我想提出的解決方案,以this postthis post後想出瞭解決方案他們都沒有爲我工作。 (但他們肯定啓發了我的解決方案)

祝你好運!