rswag icon indicating copy to clipboard operation
rswag copied to clipboard

How to handle integration tests when code throws an exception

Open jamesla opened this issue 5 years ago • 4 comments

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?

jamesla avatar May 04 '20 20:05 jamesla

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.

stale[bot] avatar Feb 11 '22 00:02 stale[bot]

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 🤔

jtannas avatar Feb 13 '22 06:02 jtannas

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.

dbenfouzari avatar Feb 28 '22 15:02 dbenfouzari

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

dbenfouzari avatar Feb 28 '22 16:02 dbenfouzari

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.

stale[bot] avatar Feb 28 '23 21:02 stale[bot]