1

In Rails Controller tests of an invalid route, this used to work before Rails-7.1 (in Minitest):

assert_raises(ActionController::RoutingError){ get "/non_existent" }

In Rails-7.1 (or later), where the default value for config.action_dispatch.show_exceptions changes into :rescuable (see Official guide), as usually defined in /config/environments/test.rb, I need to modify it for the test to pass, as

get "/non_existent"
assert_response :missing # :not_found 404

However, I think the HTTP response of 404 can be raised by a different cause from RoutingError. So, I still would like to test whether a given path is valid or not. Is there any low-level method in Rails-7.1 for it, which works regardless of the value of config.action_dispatch.show_exceptions? For example, something like the following would be ideal:

refute is_path_valid?("/non_existent", :get)
# or
assert_raises(ActionController::RoutingError){ examine_this_path("/non_existent", :get) }

I note that a temporal, on-the-spot change of config.action_dispatch.show_exceptions = :none while executing the test block would affect nothing, presumably because the config value is read once at boot and persists.

0

1 Answer 1

1

You can still cause an ActionController::RoutingError to be raised for a non existent route as follows:

assert_raises(ActionController::RoutingError) { 
  Rails.application.routes.recognize_path("/non_existent")
}

ActionDispatch::Routing::RoutingSet#recognize_path will raise that error if it can't find the path (Source)

Please note I left off the request method because the default is GET but if you needed to test other methods you can pass them as follows:

assert_raises(ActionController::RoutingError) { 
  Rails.application.routes.recognize_path("/non_existent", method: "POST")
}

Another option, which is used within Rails testing (Source), is to wrap a failed assert_recognizes in an assert_raise and interrogate that response, for instance:

err = assert_raise(Minitest::Assertion) do
  assert_recognizes({},{path:"/non_existent", method: :get}, {}, "This path does not exist")
end

assert_match err.message, "This path does not exist"
Sign up to request clarification or add additional context in comments.

3 Comments

With Rails 7.1.5.2, Rails.application.routes.recognize_path("/non_existent") raises no Exception in my environment (as I state in my question). Note that config.action_dispatch.show_exceptions = :rescuable as in default in Rails 7.1. If it was :none (or false?), the method would raise ActionController::RoutingError in the same way as in Rails-7.0.
Did you actually try it? The source code of calling that method directly has no trapping (as shown). What you stated in your question is that calling get path does not raise an exception. In this case we are not making a request at all we are asking the RouteSet directly. Regardless of what show_exceptions is set to this method still raises a ActionController::RoutingError
I figured out the routes of my app was set to capture any path… So, recognize_path always returns a Hash (even in Rails-7.0, as I realise now). The controller to deal with a random path is coded to raise ActionController::RoutingError unless the condition is satisfied; for this reason, the test suite behaves differently between Rails 7.0 and 7.1. I edited my question, deleting the part re recognize_path(). Your explanation helped me to pin down, thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.