2012-06-08 55 views
17

我不知道我在做什麼錯,但每次我嘗試測試重定向時,我得到這個錯誤:「@request必須是一個ActionDispatch ::請求「如何測試重定向與Rspec和水豚

context "as non-signed in user" do 
    it "should redirect to the login page" do 
    expect { visit admin_account_url(account, host: get_host(account)) }.to redirect_to(signin_path) 
    end 
end 
1) AdminAccountPages Admin::Accounts#show as non-signed in user should redirect to the login page 
    Failure/Error: expect { visit admin_account_url(account, host: get_host(account)) }.to redirect_to(signin_path) 
    ArgumentError: 
     @request must be an ActionDispatch::Request 
    # ./spec/requests/admin_account_pages_spec.rb:16:in `block (4 levels) in <top (required)>' 

我在水豚(1.1.2)和Rails 3.2中使用RSpec-rails(2.9.0)。如果有人能夠解釋爲什麼會發生這種情況,我將不勝感激。爲什麼我不能以這種方式使用期望?

+0

也許我錯過了一些東西,但是'assert_redirected_to'有什麼問題? –

+0

@約瑟夫魏斯曼,我得到了同樣的錯誤! – Mohamad

回答

30

水豚不是一個專門的解決方案,所以它不知道關於rails的渲染邏輯的任何東西 。

水豚專門用於集成測試,它基本上是從最終用戶與瀏覽器交互的角度來運行測試。在這些測試中,您不應該斷言模板,因爲最終用戶無法深入瞭解您的應用程序。你應該測試的是一個行動使你踏上正確的道路。

current_path.should == new_user_path 
page.should have_selector('div#erro_div') 
+1

隨着更新版本的水豚,這不再有效。我有2.10.1,並且有一個新方法'have_current_path'可以使用:'expect(page).to have_current_path(new_user_path)' – bjnord

11

錯誤消息@request must be an ActionDispatch::Request告訴你RSpec的護欄匹配器redirect_to(它代表到Rails assert_redirected_to)希望它在Rails的功能測試中使用(應ActionController::TestCase混合)。你發佈的代碼看起來像rspec-rails request spec。所以redirect_to不可用。

rspec-rails請求規範不支持檢查重定向,但在Rails集成測試中受支持。

是否應該明確檢查重定向是如何做出的(即它是301響應而不是307響應,而不是一些JavaScript)完全取決於您。

+1

感謝您解釋這一點。 – Mohamad

10

你能做到這樣:

expect(current_path).to eql(new_app_user_registration_path) 
3

這裏是hackish的解決方案,我發現

# spec/features/user_confirmation_feature.rb 

feature 'User confirmation' do 
    scenario 'provide confirmation and redirect' do 
    visit "https://stackoverflow.com/users/123/confirm" 

    expect(page).to have_content('Please enter the confirmation code') 
    find("input[id$='confirmation_code']").set '1234' 

    do_not_follow_redirect do 
     click_button('Verify') 
     expect(page.driver.status_code).to eq(302) 
     expect(page.driver.browser.last_response['Location']).to match(/\/en\//[^\/]+\/edit$/) 
    end 
    end 

    protected 

    # Capybara won't follow redirects 
    def do_not_follow_redirect &block 
    begin 
     options = page.driver.instance_variable_get(:@options) 
     prev_value = options[:follow_redirects] 
     options[:follow_redirects] = false 

     yield 
    ensure 
     options[:follow_redirects] = prev_value 
    end 
    end 
end 
+0

這有助於如果您的重定向恰好是外部鏈接 –

2

Rspec的3:

測試當前路徑是最簡單的方法:

expect(page).to have_current_path('/login?status=invalid_token')

have_current_path有一個優點這種方法:

expect(current_path).to eq('/login')

,因爲你可以包括查詢參數。

+1

這與 expect(current_path).to eq('/ login?status = invalid_token')的區別? – sekmo