27

我不知道我做错了什么,但每次我尝试测试重定向时,我都会收到此错误:“@request must be an 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 <top (required)>'

我将 RSpec-rails (2.9.0) 与 Capybara (1.1.2) 和 Rails 3.2 一起使用。如果有人也能解释为什么会发生这种情况,我将不胜感激;为什么我不能以这种方式使用期望?

4

5 回答 5

42

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

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

current_path.should == new_user_path
page.should have_selector('div#erro_div')
于 2012-06-08T20:42:14.487 回答
20

你可以这样做:

expect(current_path).to eql(new_app_user_registration_path)
于 2015-03-11T12:35:37.220 回答
15

规格 3:

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

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

与这种have_current_path方法相比,它有一个优势:

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

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

于 2016-06-11T08:10:17.587 回答
11

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

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

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

于 2012-06-09T18:55:53.373 回答
7

这是我发现的骇人听闻的解决方案

# 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
于 2015-08-05T11:35:28.960 回答