5

Note: As per RafaeldeF.Ferreira's suggestion, this question has been heavily edited since its original form.

My JSON-based app needs to return something sensible when given a bad route. We already know that the following rescue_from ActionController::RoutingError doesn't work in Rails 3.1 and 3.2:

# file: app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery
  rescue_from ActionController::RoutingError, :with => :not_found
  ...
end

(This is well documented in https://github.com/rails/rails/issues/671.) So I implemented what José Valim describes in this blog entry (item 3), and details are provided below.

But testing it has been problematic. This controller rspec test:

# 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

fails with:

ActionController::RoutingError: No route matches {:format=>"json", :controller=>"sites", :action=>"update"}

Yet this integration test calls ErrorsController#not_found and succeeds:

# 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

So: Is there a way to test the 'catch all route' using ordinary controller tests?

implementation details

If you want to see the implementation, here are the relevant code snippets

# 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
fearless_fool
  • 33,645
  • 23
  • 135
  • 217
  • The question you posed on your last update is very pertinent and we're are struggling with it too. Perhaps you should update your question body and title to focus on the behaviour of controller/integration tests in relation to the exceptions_app config. – Rafael de F. Ferreira Sep 20 '12 at 19:16
  • @RafaeldeF.Ferreira: suggestion taken -- thank you. – fearless_fool Sep 20 '12 at 19:34

0 Answers0