Rails: Testing exceptions with the rescue_responses setting

Posted . Visible to the public.

In Rails 7.2 Show archive.org snapshot the new default for config.action_dispatch.show_exceptions is rescuable.

  • :rescuable: It will show a Rails error page in the response only for rescuable exceptions as
    defined by ActionDispatch::ExceptionWrapper.rescue_responses. In the
    event of an unexpected internal server error, the exception that caused
    the error will still be raised within the test so as to provide a useful
    stack trace and a good debugging experience.
  • :all: It will show a Rails error page in the response for all exceptions (previously true)
  • :none: It will raise for all exceptions (previously false)

Using the new default needs to change a RSpec test like this:

Before

it 'raises an exception if the page could not be found' do
  expect { get '/example/' }
    .to raise_exception ActiveRecord::RecordNotFound
end

After

it 'raises an exception if the page could not be found' do
  get '/example/'
  expect(response).to have_http_status(:not_found)
end

Edge cases

In case you really need to check the underlying exception, you can temporary change the show_exception setting:

RSpec.configure do |config|
  config.around(:each, :show_exceptions) do |example|
    show_exceptions = Rails.application.env_config['action_dispatch.show_exceptions']
    Rails.application.env_config['action_dispatch.show_exceptions'] = example.metadata[:show_exceptions]

    example.run
  ensure
    Rails.application.env_config['action_dispatch.show_exceptions'] = show_exceptions
  end
end
it 'raises an exception if the page could not be found', show_exceptions: :none do
  expect { get '/example/' }
    .to raise_exception ActiveRecord::RecordNotFound
end

Additional notes regarding the implementation:

  • get '/example/', headers: { 'action_dispatch.show_exceptions' => :none } is valid, but the middleware doesn't allow to set the header from outside.
  • allow(Rails.application.config.action_dispatch).to receive(:show_exceptions).and_return(:none) is valid, but there is a underlying Rails.application.env_config object that caches the value between test. Resulting in flaky tests.
Last edit
Emanuel
License
Source code in this card is licensed under the MIT License.
Posted by Emanuel to makandra dev (2025-07-30 05:53)