dennismonsewicz
dennismonsewicz

Reputation: 25542

Rspec/Rails controller testing 404 not working

Here is my test:

  describe "GET show" do

    it "assigns service_request as @service_request" do
      get :show, { company_id: @company.id, id: service_request.id }
      expect(assigns(:service_request)).to eq service_request
    end

    it "returns 404 when service_request is not found" do
      get :show, { company_id: @company.id, id: "foo" }
      expect(response.status).to eq 404
    end

  end

The error in my terminal is:

  1) ServiceRequestsController GET show returns 404 when service_request is not found
     Failure/Error: get :show, { company_id: @company.id, id: "foo" }
     ActiveRecord::RecordNotFound:
       Couldn't find ServiceRequest with 'id'=foo [WHERE (company_id IS NOT NULL)]
     # ./spec/controllers/service_requests_controller_spec.rb:44:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

Obviously this isn't correct, but I'm not sure what's wrong

Upvotes: 4

Views: 3819

Answers (3)

Matt Hough
Matt Hough

Reputation: 1099

Just had this issue. It turns out that in the test environment, rails shows error messages to help with debugging.

This blog post details a way of getting "production-like" error responses to test your API responses. It recommends creating a helper spec/support/error_responses.rb:

module ErrorResponses

  def respond_without_detailed_exceptions
    env_config = Rails.application.env_config
    original_show_exceptions = env_config["action_dispatch.show_exceptions"]
    original_show_detailed_exceptions = env_config["action_dispatch.show_detailed_exceptions"]
    env_config["action_dispatch.show_exceptions"] = true
    env_config["action_dispatch.show_detailed_exceptions"] = false
    yield
  ensure
    env_config["action_dispatch.show_exceptions"] = original_show_exceptions
    env_config["action_dispatch.show_detailed_exceptions"] = original_show_detailed_exceptions
  end

end

RSpec.configure do |config|
  config.include ErrorResponses

  config.around(realistic_error_responses: true) do |example|
    respond_without_detailed_exceptions(&example)
  end
end

This can then be used in your case as follows. Note the use of :realistic_error_responses.

describe "GET show", :realistic_error_responses do
  it "assigns service_request as @service_request" do
    get :show, { company_id: @company.id, id: service_request.id }
    expect(assigns(:service_request)).to eq service_request
  end

  it "returns 404 when service_request is not found" do
    get :show, { company_id: @company.id, id: "foo" }
    expect(response.status).to eq 404
  end
end

Upvotes: 4

alex
alex

Reputation: 1089

A nicer way to write this is like so.

it "returns 404 when service_request is not found" do
  get :show, { company_id: @company.id, id: "foo" }
  expect(response).to have_http_status(:not_found)
end

And you can find other Rails HTTP Status symbols here.

Upvotes: -2

jkeuhlen
jkeuhlen

Reputation: 4517

Rails is throwing an ActiveRecord::RecordNotFound error instead of redirecting to a general 404 page. You need to handle that error with a rescue_from in the controller and redirect to a 404 view with status 404.

Upvotes: 3

Related Questions