Rails的“POST”成员路由响应所有请求类型

5
我想为我的“foo”控制器设置一个成员路由,它的名称是“bar”,只响应POST请求。但是,在我的RSpec测试中,我注意到它响应所有请求类型(GET、POST、PUT、DELETE)。
我原以为将路由定义为这样会限制它只响应POST请求:
resources :foo do
  member do
    post 'bar'
  do
end

这似乎得到了进一步证实,因为当我运行rake routes时,它仅显示如下的“bar”路由:
bar_foo    POST    /foo/:id/bar(.:format)    {:action=>"bar", :controller=>"foo"}

然而,从RSPEC来看,以下测试对于GET、PUT和DELETE请求失败(意味着控制器成功处理请求):
describe FooController do
    describe "GET bar" do
        it "should not be successful" do
            foo = FactoryGirl.create(:foo)
            get :bar, :id => foo.id
            response.should_not be_ok
        end
    end 
end

我错过了什么小细节吗?如何限制我的“bar”成员路由只响应“post”请求。
编辑:
这似乎是RSpec 2.0或{{link1:ActionController :: TestCase}}的问题,因为当我尝试使用除POST之外的任何东西命中我的服务器上的/ foo /:id / bar 时,我会收到以下错误:
Routing Error

No route matches [GET] "/foo/1/bar"

打印 response.inspect 并检查输出。 - Maurício Linhares
响应是200,这是FooController中'bar'函数成功执行后返回的内容。 - plainjimbo
只是为了验证您的理智,我编写了类似的测试,依赖路由来拒绝非POST等请求,并使其正常工作。这是正确的策略,可能是一些“平凡细节”导致问题。 - Woahdae
谢谢,知道自己不是疯了总是很好的 :) - plainjimbo
你的测试日志是否显示了在 get :bar 调用中实际访问的路径?它是否列出了 Started GET "/foo/:id/bar" 或其他不同的内容?此外,你的 routes.rb 文件底部是否有一个“catch-all”路由? - Ryan
没有通用路由,而且我在测试日志中也没有看到类似“Started ....”的东西。我有一种感觉,测试请求的请求方法与来自浏览器的常规请求不以相同的方式进行接口交互,我认为这与ActionController::TestCase.process如何触发请求有关。我正在查看源代码,但它有点超出了我的理解范围。 - plainjimbo
1个回答

5
根据我的经验,似乎RSpec控制器测试只要路由存在就不会尝试强制执行路由行为。RSpec确实提供了路由测试,特别是be_routable匹配器

给定以下route.rb片段:

post :foo, to: 'foo#create'

它出现了

it "won't work as expected" do
  get :foo
  expect(response).to be_ok #=> pass

  post :foo
  expect(response).to be_ok #=> pass
end

只有当route.rb完全缺失时,测试才会失败。

以下内容将通过测试,并可用于执行我们感兴趣的测试:

it "responds to only the proper HTTP verbs" do
  expect(get: :foo).not_to be_routable #=> pass - Cannot GET ‍♂️
  expect(post: :foo).to be_routable    #=> pass - POST works 
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接