2011-05-03 73 views
35

如果我有一個Devise模型用戶,其中只有角色爲admin的用戶才能查看某個url,那麼如何編寫RSpec集成測試來檢查該url的狀態是否返回200?如何使用RSpec和Devise/CanCan進行集成測試?

def login(user) 
    post user_session_path, :email => user.email, :password => 'password' 
end 

這是僞建議在回答這個問題:Stubbing authentication in request spec,但我不能爲我的生命得到它與色器件的工作。 CanCan在檢查Ability時會收到一個零用戶,這個用戶自然沒有正確的權限。

在集成規範中無法訪問控制器,所以我不能存根current_user,但我想要做這樣的事情。

describe "GET /users" do 
    it "should be able to get" do 
    clear_users_and_add_admin #does what it says... 
    login(admin) 
    get users_path 
    response.status.should be(200) 
    end 
end 

注意!:自問題提出後,所有這些都發生了變化。要做到這一點目前最好的辦法是在這裏:http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara

+2

注:這一切都已經改變,因爲有人問。要做到這一點目前最好的辦法是在這裏:http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara只是重申第一嘆息讀者喜歡我 – 2012-11-25 11:15:20

回答

47

@ pschuegr自己的答案讓我跨線。爲了完整,這是我做的是讓我輕鬆地建立了兩個要求的規格和控制器的規格(使用FactoryGirl用於創建用戶實例):

在/spec/support/sign_in_support.rb

#module for helping controller specs 
module ValidUserHelper 
    def signed_in_as_a_valid_user 
    @user ||= FactoryGirl.create :user 
    sign_in @user # method from devise:TestHelpers 
    end 
end 

# module for helping request specs 
module ValidUserRequestHelper 

    # for use in request specs 
    def sign_in_as_a_valid_user 
    @user ||= FactoryGirl.create :user 
    post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password 
    end 
end 

RSpec.configure do |config| 
    config.include ValidUserHelper, :type => :controller 
    config.include ValidUserRequestHelper, :type => :request 
end 

然後,在請求規格:

describe "GET /things" do 
    it "test access to things, works with a signed in user" do 
    sign_in_as_a_valid_user 
    get things_path 
    response.status.should be(200) 
    end 
end 

describe "GET /things" do 
    it "test access to things, does not work without a signed in user" do 
    get things_path 
    response.status.should be(302) # redirect to sign in page 
    end 
end 

並且類似地,使用 'signed_in_as_valid_user' 在控制器的規格(它封裝設計:: TestHelpers sign_in方法與來自FactoryGirl的用戶)

+0

我已經定義了與你所提到的相同的模塊,但是對於#(NameError)'',我得到了這個錯誤'未定義的局部變量或方法'sign_in_as_a_valid_user'。我在哪裏犯錯誤? – rohitmishra 2012-10-08 12:54:10

+0

這是一個請求規範,對吧?你的'Rspec.configure'代碼是否正在執行? – 2012-10-09 00:20:38

+0

是的,這是在一個請求規範。如何檢查'Rspec.configure'代碼是否執行? – rohitmishra 2012-10-09 07:10:19

0

您可以創建一個宏(/spec/support/controller_macros.rb),寫類似:

module ControllerMacros 
    def login_user 
    before(:each) do 
     @request.env["devise.mapping"] = :user 
     @user = Factory(:user) 
     sign_in @user 
    end 
    end 
end 

您還可以包括任何慘慘屬性您想。然後,在你的規格:

describe YourController do 
    login_user 

    it "should ..." do 

    end 
+3

感謝您的評論斯皮羅斯,但它在使用Devise :: TestHelpers的控制器中工作正常。只是在請求規範中它不起作用(@request爲零)。 – pschuegr 2011-05-03 06:16:21

+0

你提到你收到一個零用戶。這意味着規範不會登錄用戶。你確定你使用設計助手並正確登錄?你可以在你的規範裏面測試一下,以確保。如果沒有,你可以嘗試上面的代碼。我認爲這一切都來自於你的規範不會登錄用戶。 – Spyros 2011-05-03 06:26:08

+2

這個答案適用於控制器測試,而不是集成測試,就像問題所在 - 關於提問者提出的零用戶評論是因爲答案是錯誤的情況 – Houen 2011-07-05 14:58:56

28

啊,太近了。這就是訣竅 - 我錯過了正確的參數形式和重定向。

post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password 
+0

正是我在尋找的東西。謝謝!˚F – John 2011-08-16 02:46:19

+4

我不得不使用'page.driver.post',而不是'post_via_redirect'(要求規格) – 2011-09-18 18:29:08

+2

嘿,我怎麼能用戶CURRENT_USER在要求規範測試用例就像我們在控制器規範測試用例如何使用 – sharath 2012-07-10 12:05:28

20

我使用了一個稍微不同的方法,使用Warden :: Test :: Helpers。

在我的規格/支持/ macros.rb我說:

module RequestMacros 
    include Warden::Test::Helpers 

    # for use in request specs 
    def sign_in_as_a_user 
    @user ||= FactoryGirl.create :confirmed_user 
    login_as @user 
    end 
end 

然後包括在RSpec中在spec_helper.rb配置:

RSpec.configure do |config| 
    config.include RequestMacros, :type => :request 
end 

然後在要求規範自己:

describe "index" do 
    it "redirects to home page" do 
    sign_in_as_a_user 
    visit "/url" 
    page.should_not have_content 'content' 
    end 
end 

與此相反的post_via_redirect user_session_path方法,這實際工作和所有例如,允許我在before_filters中使用current_user。

+0

維基文章:https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara – 2012-08-14 09:25:57

0

截至2017年中期,我們又多了一個,在我看來,更好的opprotunity制定我們Rspecs整合。我們能夠利用與定義的helper方法sign in存根authentization如下所述:

module ControllerHelpers 
    def sign_in(user = double('user')) 
     if user.nil? 
     allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user}) 
     allow(controller).to receive(:current_user).and_return(nil) 
     else 
     allow(request.env['warden']).to receive(:authenticate!).and_return(user) 
     allow(controller).to receive(:current_user).and_return(user) 
     end 
    end 
    end 

你還應該附加在spec_helper.rbrails_helper.rb引用新創建的文件:

require 'support/controller_helpers' 
    ... 
    RSpec.configure do |config| 
    ... 
    config.include Devise::TestHelpers, :type => :controller 
    config.include ControllerHelpers, :type => :controller 
    ... 
    end 

然後在方法只是發生在方法正文sign_in的開始,用於已認證用戶的上下文,並且您都已設置。最新的細節可以在色器件文檔中找到here