Test for HTTP status code in some RSpec rails request exampes, but for raised exception in others
You'd want to use RSpec filters for that. If you do it this way, the modification to Rails.application.config.action_dispatch.show_exceptions
will be local to the example and not interfere with your other tests:
# This configure block can be moved into a spec helperRSpec.configure do |config| config.before(:example, exceptions: :catch) do allow(Rails.application.config.action_dispatch).to receive(:show_exceptions) { true } endendRSpec.describe 'POST' do let(:perform_request) { post '/my/api/my_ressource', request_body } context 'without mandatory attribute' do let(:request_body) do {}.to_json end it 'raises a ParameterMissing error' do expect { perform_request }.to raise_error ActionController::ParameterMissing end context 'in production', exceptions: :catch do it 'reports BAD REQUEST (HTTP status 400)' do perform_request expect(response).to be_a_bad_request end end endend
The exceptions: :catch
is "arbitrary metadata" in RSpec speak, I chose the naming here for readability.
Returning nil
from a partially mocked application config with
context 'in production' do before do allow(Rails.application.config.action_dispatch).to receive(:show_exceptions) end it 'reports BAD REQUEST (HTTP status 400)' do perform_request expect(response).to be_a_bad_request end end
or more explicitly with
context 'in production' do before do allow(Rails.application.config.action_dispatch).to receive(:show_exceptions).and_return nil end it 'reports BAD REQUEST (HTTP status 400)' do perform_request expect(response).to be_a_bad_request end end
would work if that was the only example being run. But if it was, we could just as well drop the setting from config/environments/test.rb
, so this is a bit moot. When there are several examples, this will not work, as Rails.application.env_config()
, which queries this setting, caches its result.
Mocking Rails.application.env_config()
to return a modified result
context 'in production' do before do # We don't really want to test in a production environment, # just in a slightly deviating test environment, # so use the current test environment as a starting point ... pseudo_production_config = Rails.application.env_config.clone # ... and just remove the one test-specific setting we don't want here: pseudo_production_config.delete 'action_dispatch.show_exceptions' # Then let `Rails.application.env_config()` return that modified Hash # for subsequent calls within this RSpec context. allow(Rails.application).to receive(:env_config). and_return pseudo_production_config end it 'reports BAD REQUEST (HTTP status 400)' do perform_request expect(response).to be_a_bad_request end end
will do the trick. Note that we clone
the result from env_config()
, lest we modify the original Hash which would affect all examples.