我有以下情况:
EDITED
在我的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
EDITED
我的控制器:
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/v1/foo
EDITED
当我的api中没有其他路径可用时,使用自定义 json 404响应触发此路由的目的。当我们访问以下路线时,此路线和控制器正在按预期工作:/api/v1/bar
或POST /7fa070bc-4e98-4bd1-b525-d5564b918e4c
如何正确编写测试?
其他信息:Rails 4.2.6,Rspec 3.5.4
答案 0 :(得分:1)
看一下这个链接:
https://apidock.com/rails/ActionDispatch/Routing/Mapper/Base/match
它说:
请注意:controller,:action和:id被解释为url查询参数,因此可以通过动作中的params获得。
匹配&#34;:controller /:action /:id&#34;
您的路线是:
match '*path', to: 'unmatch_route#not_found', via: :all
所以你的测试试图找到一条路线:action =&gt;&#34; not_found&#34; inside:controller =&gt;&#34; api / v1 / unmatch_route&#34;。但是你的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'
答案 1 :(得分:1)
如果您尝试编写路线规范,它也不会起作用,它会返回一些奇怪的东西。
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之外,它返回了path =&gt;无法控制的原因可能是控制器规格无法按预期工作的原因。因此,您可以使用下面的请求测试代替控制器测试。
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
答案 2 :(得分:0)
我还发现自己想要测试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
参考: