RSpec + 水豚:redirect_to 外部页面将我送回 root_path

RSpec + Capybara: redirect_to external page sends me back to root_path

我正在尝试编写一个功能测试来检查转到特定路径是否会将用户重定向到外部网站。

为了在我的测试中禁止外部连接,我在 spec_helper.rb 中有以下内容:

require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)

我的规范是这样的:

it 'redirects safely' do
  visit "/some/route"

  expect(page).not_to have_content 'MyWebsite'
end

在我的 ApplicationController 中,我有一个 before_action 应该根据条件从外部重定向:

class ApplicationController < ActionController::Base
  before_action :redirect_to_external_website, if: :unsupported_path

  private

  def redirect_to_external_website
    redirect_to 'https://some.other.website'
  end

  def unsupported_path
    # Some conditions
  end 
end

重定向在开发中按预期工作。

但是,当我 运行 规范时,我可以看到发生了两次重定向(我认为 redirect_to_external_website 方法被命中了两次)然后它返回到我的根路径。

知道我做错了什么吗?

提前致谢!

因为您没有指定您与 Capybara 一起使用的驱动程序 - https://github.com/teamcapybara/capybara#drivers - 我假设您使用的是默认的 rack_test 驱动程序。

rack_test 驱动程序不支持对外部 url 的请求(域信息被忽略,所有路径都直接路由到 AUT)所以您的测试实际上并没有测试您认为的内容redirect_to 'https://some.other.website' 实际上只是重定向到本地应用程序中的 / (因为 rack_test 驱动程序看到 'https://some.other.website/' ,忽略所有域内容并将其视为 '/ ' 在您的被测应用程序中)。

如果您碰巧使用了 Capybara 支持的其他驱动程序之一,该驱动程序确实支持外部 URL(selenium、poltergeist、capybara-webkit 等),那么您的 WebMock 并没有像您认为的那样工作,因为它只控制你的 AUT 发出的请求,它不控制那些驱动程序使用的 "browsers" 所做的任何事情,所以他们可以自由地向外部 URL 发出请求。

您尝试测试的功能更适合通过请求规范进行测试 - https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec - 而不是通过 feature/system 规范进行测试。