How to handle integration tests when code throws an exception
I am trying to work out how to handle the situation of testing a record that doesn't exist with the response function.
In my controller I have a normal set method:
def set_mode
@mode = Mode.find(params[:id])
end
When I curl localhost:3000/mode/123 I get a 404 back and get the following message in the rails server - working as expected:
ActiveRecord::RecordNotFound (Couldn't find Mode with 'id'=123):
app/controllers/modes_controller.rb:19:in `set_mode'
However when I run the following test it fails because of the exception and never bothers to check for the 404:
response '404', 'not_found' do
let(:id) { 123 }
run_test!
end
With the following output:
Failures:
1) Mode /modes/{id} get not_found returns a 404 response
Failure/Error: @mode = Mode.find(params[:id])
ActiveRecord::RecordNotFound:
Couldn't find Mode with 'id'=123
What is the intended way to handle this with rswag?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If the issue is still relevant to you, please leave a comment stating so to keep the issue from being closed. Thank you for your contributions.
heyo - new volunteer here clearing out the issue backlog and found this
So I learned something new about Rails digging into this... It looks like ActiveRecord::RecordNotFound is an unhandled exception in your app, so I was a bit surprised you were getting a 404 page instead of a 500. Turns out there's some Rails magic that turns it into a 404 page: https://stackoverflow.com/questions/27925282/activerecordrecordnotfound-raises-404-instead-of-500
I'd never noticed before since I've been handling exceptions explicitly using rescue_from in my ApplicationController and RSwag has been happy with it. eg.
Example
rescue_from ActionController::RoutingError, with: ->(e) { handle_exception(e, log_level: :error, status: :not_found) }
rescue_from ActiveRecord::RecordNotFound, with: ->(e) { handle_exception(e, log_level: :warn, status: :not_found) }
rescue_from ActiveRecord::RecordNotDestroyed, with: ->(e) { handle_exception(e, log_level: :warn, status: :unprocessable_entity) }
rescue_from ActiveRecord::RecordInvalid, with: ->(e) { handle_exception(e, log_level: :warn, status: :unprocessable_entity) }
rescue_from ActiveRecord::StaleObjectError, with: ->(e) { handle_exception(e, log_level: :warn, status: :conflict) }
rescue_from ActionController::ParameterMissing, with: ->(e) { handle_exception(e, log_level: :warn, status: :bad_request) }
def handle_exception(exception, log_level:, status:)
LoggingService.log_exception(exception: exception, log_level: log_level)
@exception = exception
respond_to do |format|
format.html { render html: "ERROR: #{exception&.message}", status: status }
format.json do
render partial: "api/v1/errors/#{exception&.class&.name&.to_s&.underscore}", status: status
end
end
end
It seems yours is failing because the exception is bubbling up into the test instead of being caught by ActionDispatch::ExceptionWrapper. I don't know any more than that yet but it seems worth digging into 🤔
It looks weird that no one gave an answer since May 2020. I got this error too and don't know how to fix it.
I managed to fix it by adding this piece of code in app/controllers/application_controller.rb
class ApplicationController < ActionController::API
rescue_from ActiveRecord::RecordNotFound do |ex|
render json: { status: 404, error: ex.to_s }, status: 404
end
end
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If the issue is still relevant to you, please leave a comment stating so to keep the issue from being closed. Thank you for your contributions.