【问题标题】:Do routing specs support redirect routes? [RSpec]路由规范是否支持重定向路由? [R规格]
【发布时间】:2012-05-31 23:07:20
【问题描述】:

在对这个问题进行了相当深入的研究之后,我在对文档的理解和结果之间陷入了僵局。

根据https://www.relishapp.com/rspec/rspec-rails/v/2-8/docs/routing-specs/route-to-matcher,我们应该可以这样写:

#rspec-rails (2.8.1)
#rspec (>= 1.3.1)
#rspec-core (~> 2.8.0)

# routing spec
require "spec_helper"

describe BusinessUsersController do
  describe "routing" do
    it "routes to some external url" do
      get("/business_users/7/external_url").should route_to("http://www.google.com")
    end
  end
end

# routes.rb
BizeebeeBilling::Application.routes.draw do

  resources :business_users do
    member do
      get "external_url" => redirect("http://www.google.com")
    end
  end
end

运行此规范会产生以下结果: 失败:

  1) BusinessUsersController routing routes to some external url
     Failure/Error: assert_routing "/business_users/7/external_url", "http://www.google.com"
     ActionController::RoutingError:
       No route matches "/business_users/7/external_url"
     # ./spec/routing/business_users_routing_spec.rb:19:in `block (3 levels) in <top (required)>'

我无法在任何地方找到任何人报告此特定问题。

添加细节:手动测试时路由解析得很好。

【问题讨论】:

    标签: ruby-on-rails rspec


    【解决方案1】:

    路由规范/测试专门测试路由是否映射到特定的控制器和操作(可能还有一些参数)。

    我深入研究了 Rails 和 Journey 的内部结构。 RSpec 和 Rails(基本上省略了一些细节)使用Rails.application.routes.recognize_path 来回答问题“这是可路由的吗?”

    例如:

    $ 导轨控制台 > Rails.application.routes.recognize_path("/business_users/1", 方法:"GET") => {:action=>"show", :controller=>"business_users", :id=>"1"}

    但是,/business_users/1/external_url 的另一端没有控制器。事实上,为了执行重定向,Rails 创建了一个ActionDispatch::Routing::Redirect 的实例,这是一个小型 Rack 应用程序。从来没有碰过 Rails 控制器。您基本上是在安装另一个 Rack 应用程序来执行重定向。

    要测试重定向,我建议改用请求规范(spec/requests 中的文件)。比如:

    require "spec_helper"
    
    describe "external redirection" do
      it "redirects to google.com" do
        get "/business_users/1/external_url"
        response.should redirect_to("http://www.google.com")
      end
    end

    这会隐式测试路由,并允许您针对重定向进行测试。

    【讨论】:

    • 这很好理解,但是我在尝试这个时遇到了问题。在我的 Rspec before 块中,我加载了 seeds.rb,因为即使在测试中也需要一些基线数据。但是由于重定向使用了一个小型 Rack 应用程序,因此对于我的任何模型,加载 seeds.rb 失败并显示“找不到表”,大概是因为非 Rails Rack 小程序不使用 ActiveRecord。所以我没有很好的方法来对基于重定向的路由进行回归,这些路由在应用程序中确实有效,但我无法通过测试。 :-(
    • expect(response).to redirect_to("http://www.google.com") 如果你不喜欢“应该”的语法。
    【解决方案2】:

    安迪·林德曼有正确的答案。但是,您不必将规范放在规范/请求中,您可以将其保留在规范/路由中,并使用元数据“类型”明确:describe 'my route', type: :request do

    【讨论】:

    • 我试过了,但仍然没有在规范的上下文中找到响应对象
    • 在摆弄了一下之后,看起来 rspec 不允许我覆盖规范/路由路径中的规范类型。如果我将它移到外部并将其放在规范/请求或规范/api 下,它就可以工作。我将为此在 rspec-rails 中打开一个问题。
    【解决方案3】:

    我遇到了类似的情况,我试图测试一系列路由,一些应该重定向,一些不应该重定向。我想将它们保留在一个路由规范中,因为这是对它们进行分组的最合乎逻辑的方式。

    我尝试使用describe: 'my route', type: request,但发现不起作用。但是,您可以在规范上下文中包含 RSpec::Rails::RequestExampleGroup 以访问请求规范方法。比如:

    describe "My Routes" do
      context "Don't Redirect" do
        it "gets URL that doesn't redirect" do
          get("business_users/internal_url").should route_to(controller: "business_users", action: "internal_url_action")
        end
      end
    
      context "Redirection" do
        include RSpec::Rails::RequestExampleGroup
        it "redirects to google.com" do
          get "/business_users/1/external_url"
          response.should redirect_to("http://www.google.com")
        end
      end
    end
    

    【讨论】:

      【解决方案4】:

      测试外部重定向的最简单方法是使用集成测试:

        test "GET /my_page redirects Google" do
          get "/my_page"
          assert_redirected_to "https://google.com"
        end
      

      您的测试需要在您的 test/integration 目录下或集成测试所在的等效目录下。

      【讨论】:

      • 在 rspec 这将是一个请求规范
      【解决方案5】:

      我想你想要redirect_to matcher

      【讨论】:

      • redirect_to 匹配器在路由规范中不可用。此外,错误不在匹配器中,而是在运行测试时没有拾取在 routes.rb 中明确定义的路由。另外一点,在手动测试时,路由本身运行良好。
      • 如果不是控制器规范,那为什么要以describe BusinessUsersController开头?
      • 你说得对。但是,这些是生成的。我想这完全是一个单独的问题:(
      猜你喜欢
      • 1970-01-01
      • 2017-06-30
      • 2019-01-20
      • 1970-01-01
      • 2011-05-29
      • 2016-12-15
      • 2019-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多