如何使用Rspec和Capybara测试重定向

我不知道我做错了什么,但每次我尝试测试重定向时,都会收到此错误:“@request必须是ActionDispatch :: Request”

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 ' 

我正在使用带有Capybara(1.1.2)和Rails 3.2的RSpec-rails(2.9.0)。 如果有人能解释为什么会这样,我将不胜感激; 为什么我不能以这种方式使用期望?

Capybara不是特定于rails的解决方案,所以它对rails的渲染逻辑一无所知。

Capybara专门用于集成测试,它实质上是从最终用户与浏览器交互的角度运行测试。 在这些测试中,您不应该断言模板,因为最终用户无法深入了解您的应用程序。 你应该测试的是一个动作让你走上正确的道路。

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

你可以这样做:

 expect(current_path).to eql(new_app_user_registration_path) 

错误消息@request must be an ActionDispatch::Request告诉你rspec-rails matcher redirect_to (它委托给Rails assert_redirected_to )期望它在Railsfunction测试中使用(应该在ActionController::TestCase混合使用)。 您发布的代码看起来像rspec-rails请求规范。 所以redirect_to不可用。

rspec-rails请求规范不支持检查重定向,但Rails集成测试支持。

是否应该明确检查重定向是如何进行的(它是301响应而不是307响应而不是某些javascript)完全取决于您。

Rspec 3:

测试当前路径的最简单方法是:

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

have_current_path比这种方法有优势:

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

因为你可以包含查询参数。

这是我发现的hackish解决方案

 # spec/features/user_confirmation_feature.rb feature 'User confirmation' do scenario 'provide confirmation and redirect' do visit "/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