注:RafaeldeF.Ferreiraの提案によると、この質問は元の形式から大幅に編集されています。
私のJSONベースのアプリは、悪いルートが与えられたときに賢明なものを返す必要があります。rescue_from ActionController::RoutingError
Rails3.1および3.2では以下が機能しないことはすでにわかっています。
# file: app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
rescue_from ActionController::RoutingError, :with => :not_found
...
end
(これはhttps://github.com/rails/rails/issues/671に詳しく記載されています。)そこで、JoséValimがこのブログエントリ(項目3)で説明していることを実装しました。詳細は、以下に記載されています。
しかし、それをテストすることは問題がありました。このコントローラーのrspecテスト:
# file: spec/controllers/errors_controller.rb
require 'spec_helper'
require 'status_codes'
describe ErrorsController do
it "returns not_found status" do
get :not_found
response.should be(StatusCodes::NOT_FOUND)
end
end
失敗する:
ActionController::RoutingError: No route matches {:format=>"json", :controller=>"sites", :action=>"update"}
しかし、この統合テストはErrorsController#not_foundを呼び出し、成功します。
# file: spec/requests/errors_spec.rb
require 'spec_helper'
require 'status_codes'
describe 'errors service' do
before(:each) do
@client = FactoryGirl.create(:client)
end
it "should catch routing error and return not_found" do
get "/v1/clients/login.json?id=#{@client.handle}&password=#{@client.password}"
response.status.should be(StatusCodes::OK)
post "/v1/sites/impossiblepaththatdoesnotexist"
response.status.should be(StatusCodes::NOT_FOUND)
end
end
だから:通常のコントローラーテストを使用して「すべてのルートをキャッチ」をテストする方法はありますか?
実装の詳細
実装を確認したい場合は、関連するコードスニペットを次に示します。
# config/routes.rb
MyApp::Application.routes.draw do
... all other routes above here.
root :to => "pages#home"
match "/404", :to => "errors#not_found"
end
# config/application.rb
module MyApp
class Application < Rails::Application
config.exceptions_app = self.routes
...
end
end
# config/environments/test.rb
MyApp::Application.configure do
...
config.consider_all_requests_local = false
...
end
# app/controllers/errors_controller.rb
class ErrorsController < ApplicationController
def not_found
render :json => {:errors => ["Resource not found"]}, :status => :not_found
end
end