如何在 rails 中测试自定义的 not_found 路由
How to test a customized not_found route in rails
我有以下情况:
已编辑
在我的routes.rb
namespace :api, defaults: { format: :json } do
namespace :v1 do
# the definitions of other routes of my api
# ...
match '*path', to: 'unmatch_route#not_found', via: :all
end
end
已编辑
我的控制器:
class Api::V1::UnmatchRouteController < Api::V1::ApiController
def not_found
respond_to do |format|
format.json { render json: { error: 'not_found' }, status: 404 }
end
end
end
我的测试如图:
require 'rails_helper'
RSpec.describe Api::V1::UnmatchRouteController, type: :controller do
describe 'get response from unmatched route' do
before do
get :not_found, format: :json
end
it 'responds with 404 status' do
expect(response.status).to eq(404)
end
it 'check the json response' do
expect(response.body).to eq('{"error": "not_found"}')
end
end
end
这对我来说似乎是正确的,但是我对两个 it
语句都得到了相同的错误:
1) Api::V1::UnmatchRouteController get response from unmatched route responds with 404 status
Failure/Error: get :not_found, format: :json
ActionController::UrlGenerationError:
No route matches {:action=>"not_found", :controller=>"api/v1/unmatch_route", :format=>:json}
# /home/hohenheim/.rvm/gems/ruby-2.3.1@dpms-kaefer/gems/gon-6.1.0/lib/gon/spec_helpers.rb:15:in `process'
# ./spec/controllers/api/v1/unmatch_route_controller_spec.rb:14:in `block (3 levels) in <top (required)>'
已编辑
当我的 api 中没有其他可能的路由时,使用自定义 json 404 响应 会触发此路由的目的。当我们访问如下路由时,此路由和控制器现在按预期工作:/api/v1/foo
或 /api/v1/bar
如何正确编写测试?
附加信息:Rails 4.2.6,Rspec 3.5.4
看看这个link:
https://apidock.com/rails/ActionDispatch/Routing/Mapper/Base/match
它说:
Note that :controller, :action and :id are interpreted as url query parameters and thus available through params in an action.
match ":controller/:action/:id"
您的路线是:
match '*path', to: 'unmatch_route#not_found', via: :all
所以你的测试试图找到一个路由:action=>"not_found" inside :controller=>"api/v1/unmatch_route"。但是你的routes.rb没有这条路线。
尝试这样的事情:
match 'unmatch_route/not_found', to: 'unmatch_route#not_found', via: :all
如果你真的需要使用 *path 试试这个:
match '/:path/', :to => 'unmatch_route#not_found', :path=> /.*/, :as =>'not_found'
如果您尝试编写路由规范,它也不会起作用,而且会 return 一些奇怪的东西。
Failure/Error:
expect(get("/unmatch")).
to route_to("unmatch_route#not_found")
The recognized options <{"controller"=>"unmatch_route", "action"=>"not_found", "path"=>"unmatch"}> did not match <{"controller"=>"unmatch_route", "action"=>"not_found"}>, difference:.
--- expected
+++ actual
@@ -1 +1 @@
-{"controller"=>"unmatch_route", "action"=>"not_found"}
+{"controller"=>"unmatch_route", "action"=>"not_found", "path"=>"unmatch"}
除了操作 not_found,它 returned 路径 => 不匹配,这可能是控制器规范未按预期工作的原因。因此,您可以使用请求测试代替控制器测试,如下所示。
require 'rails_helper'
RSpec.describe "get response from unmatched route", :type => :request do
before do
get '/not_found', format: :json
end
it 'responds with 404 status' do
expect(response.status).to eq(404)
end
it 'check the json response' do
expect(response.body).to eq('{"error": "not_found"}')
end
end
我还发现自己想测试 API 错误的响应是渲染 JSON,而不是编写一个简单地拯救 ActionController::RoutingError
.
的规范
以下 request spec 对我有用,使用 Rails 6.0 & RSpec 3.9:
require 'rails_helper'
RSpec.describe '404 response for API endpoints' do
it 'renders an error in JSON' do
render_exceptions do
get '/api/v1/fictional-endpoint', headers: { 'Accept' => 'application/json' }
end
expect(response).to have_http_status(:not_found)
expect(response['Content-Type']).to include('application/json')
expect(json_response.fetch(:errors)).to include('Not found')
end
private
def json_response
JSON.parse(response.body, symbolize_names: true)
end
def render_exceptions
env_config = Rails.application.env_config
original_show_exceptions = env_config['action_dispatch.show_exceptions']
original_show_detailed_exceptions = env_config['action_dispatch.show_detailed_exceptions']
env_config['action_dispatch.show_exceptions'] = true
env_config['action_dispatch.show_detailed_exceptions'] = false
yield
ensure
env_config['action_dispatch.show_exceptions'] = original_show_exceptions
env_config['action_dispatch.show_detailed_exceptions'] = original_show_detailed_exceptions
end
end
参考文献:
我有以下情况:
已编辑
在我的routes.rb
namespace :api, defaults: { format: :json } do
namespace :v1 do
# the definitions of other routes of my api
# ...
match '*path', to: 'unmatch_route#not_found', via: :all
end
end
已编辑
我的控制器:
class Api::V1::UnmatchRouteController < Api::V1::ApiController
def not_found
respond_to do |format|
format.json { render json: { error: 'not_found' }, status: 404 }
end
end
end
我的测试如图:
require 'rails_helper'
RSpec.describe Api::V1::UnmatchRouteController, type: :controller do
describe 'get response from unmatched route' do
before do
get :not_found, format: :json
end
it 'responds with 404 status' do
expect(response.status).to eq(404)
end
it 'check the json response' do
expect(response.body).to eq('{"error": "not_found"}')
end
end
end
这对我来说似乎是正确的,但是我对两个 it
语句都得到了相同的错误:
1) Api::V1::UnmatchRouteController get response from unmatched route responds with 404 status
Failure/Error: get :not_found, format: :json
ActionController::UrlGenerationError:
No route matches {:action=>"not_found", :controller=>"api/v1/unmatch_route", :format=>:json}
# /home/hohenheim/.rvm/gems/ruby-2.3.1@dpms-kaefer/gems/gon-6.1.0/lib/gon/spec_helpers.rb:15:in `process'
# ./spec/controllers/api/v1/unmatch_route_controller_spec.rb:14:in `block (3 levels) in <top (required)>'
已编辑
当我的 api 中没有其他可能的路由时,使用自定义 json 404 响应 会触发此路由的目的。当我们访问如下路由时,此路由和控制器现在按预期工作:/api/v1/foo
或 /api/v1/bar
如何正确编写测试?
附加信息:Rails 4.2.6,Rspec 3.5.4
看看这个link:
https://apidock.com/rails/ActionDispatch/Routing/Mapper/Base/match
它说:
Note that :controller, :action and :id are interpreted as url query parameters and thus available through params in an action.
match ":controller/:action/:id"
您的路线是:
match '*path', to: 'unmatch_route#not_found', via: :all
所以你的测试试图找到一个路由:action=>"not_found" inside :controller=>"api/v1/unmatch_route"。但是你的routes.rb没有这条路线。
尝试这样的事情:
match 'unmatch_route/not_found', to: 'unmatch_route#not_found', via: :all
如果你真的需要使用 *path 试试这个:
match '/:path/', :to => 'unmatch_route#not_found', :path=> /.*/, :as =>'not_found'
如果您尝试编写路由规范,它也不会起作用,而且会 return 一些奇怪的东西。
Failure/Error:
expect(get("/unmatch")).
to route_to("unmatch_route#not_found")
The recognized options <{"controller"=>"unmatch_route", "action"=>"not_found", "path"=>"unmatch"}> did not match <{"controller"=>"unmatch_route", "action"=>"not_found"}>, difference:.
--- expected
+++ actual
@@ -1 +1 @@
-{"controller"=>"unmatch_route", "action"=>"not_found"}
+{"controller"=>"unmatch_route", "action"=>"not_found", "path"=>"unmatch"}
除了操作 not_found,它 returned 路径 => 不匹配,这可能是控制器规范未按预期工作的原因。因此,您可以使用请求测试代替控制器测试,如下所示。
require 'rails_helper'
RSpec.describe "get response from unmatched route", :type => :request do
before do
get '/not_found', format: :json
end
it 'responds with 404 status' do
expect(response.status).to eq(404)
end
it 'check the json response' do
expect(response.body).to eq('{"error": "not_found"}')
end
end
我还发现自己想测试 API 错误的响应是渲染 JSON,而不是编写一个简单地拯救 ActionController::RoutingError
.
以下 request spec 对我有用,使用 Rails 6.0 & RSpec 3.9:
require 'rails_helper'
RSpec.describe '404 response for API endpoints' do
it 'renders an error in JSON' do
render_exceptions do
get '/api/v1/fictional-endpoint', headers: { 'Accept' => 'application/json' }
end
expect(response).to have_http_status(:not_found)
expect(response['Content-Type']).to include('application/json')
expect(json_response.fetch(:errors)).to include('Not found')
end
private
def json_response
JSON.parse(response.body, symbolize_names: true)
end
def render_exceptions
env_config = Rails.application.env_config
original_show_exceptions = env_config['action_dispatch.show_exceptions']
original_show_detailed_exceptions = env_config['action_dispatch.show_detailed_exceptions']
env_config['action_dispatch.show_exceptions'] = true
env_config['action_dispatch.show_detailed_exceptions'] = false
yield
ensure
env_config['action_dispatch.show_exceptions'] = original_show_exceptions
env_config['action_dispatch.show_detailed_exceptions'] = original_show_detailed_exceptions
end
end
参考文献: