如何使用 rspec 在控制器中测试自定义路由

How to test custom routes in controller with rspec

我在中定义了一个自定义路由 routes.rb

get "packages/city/:location_id",  to: "packages#index"

controller_spec.rb

get :index

给出这个错误,

ActionController::UrlGenerationError:
   No route matches {:action=>"index", :controller=>"packages"}

如何在控制器规范中明确指定自定义路由?

如果您这样声明您的路线,也许会有帮助?

get "packages/city/:location_id" => "packages#index"

记得在规范中提供 location_id 参数,例如get :index, location_id: 1.

因为你没有通过location_id

路由定义为匹配:

/packages/city/:location_id

所以为了遵守它,你需要做类似

的事情

get :index, location_id: 1234

控制器规格有同样的问题:

# rake routes | grep media_order
teacher_work_media_orders PATCH /teacher/works/:work_id/media_orders(.:format)  teacher/media_orders#update

当我这样做的时候:

# spec/controller/teacher/media_orders_controller
patch :update data: {}

我得到了

 Failure/Error: patch :update
 ActionController::UrlGenerationError:
   No route matches {:action=>"update", :controller=>"teacher/media_orders"}

但当我这样做时

patch :update, work_id: 1234, data: {}

有效

2017

我尝试了上面的解决方案,但它们没有用。我得到了:

ArgumentError:
   unknown keyword: location_id

似乎 RSpec 现在需要一个 params 参数。相应的调用如下所示:

get(:index, params: { location_id: 123 })

2019

正在解决我的控制器规格中的同样错误。尝试接受并跟进解决方案,但它们也没有用,要么导致无方法错误,要么持续出现无路由匹配错误。

像接受的解决方案那样直接定义路由也不满足错误。

经过多次搜索和一些键盘粉碎测试通过。

注意事项

  • 控制器用于多态资源
  • 路由嵌套在 resources :location, only[:index, :show] do ... end
  • 这是 API 条路线,所以 JSON 只有

解决方案

let(:location) do
    create(:location)
  end


shared_examples("a user who can't manage locations") do
    describe 'GET #index' do
      it 'denies access' do

        get :index, params:{location_id: location.locationable.id, format: :json}
        expect(response).to have_http_status :unauthorized
      end
    end
end

所以最后它是两种解决方案的组合,但必须将它们放在 params hash 中否则它会抛出 name/no 方法或路由错误

结论

  • 对关联的引用必须在参数哈希中
  • 即使控制器responds_to:json,它也会抛出错误,没有路由错误
  • 必须在您的请求中包含数据哈希,否则不会出现路由匹配错误

希望这对您有所帮助,

干杯!