In Rails 3, when writing functional tests in MiniTest, I used to test routes separately from testing my actions with the controller. I got the idea from the Rails Guide on Testing - Section 9: Testing Routes . However, after upgrading my application to Rails 4, I noticed that the tests with the controller themselves began to deviate from unknown routes if I did not provide the get|patch|post|delete method with the correct set of parameters.
For example, given routes:
# config/routes.rb namespace "api" do namespace "v2", defaults: { format: :json } do resources :users do resources :posts do resources :comments end end end end
And a functional test:
# test/controllers/api/v2/comments_controller_test.rb describe Api::V2::CommentsController it "does something" do get :index end end
In Rails 3, this will work. But in Rails 4, I get a URL generation error:
ActionController :: UrlGenerationError: route mapping {: action => "index" ,: controller => "api / v2 / comments"}
From this, I can conclude that the get helper simply could not map the route to the routes file when trying to find the controller and action. Fair. I can fix this by changing the get call to include the parameters needed to satisfy the nested route, for example:
# test/controllers/api/v2/comments_controller_test.rb describe Api::V2::CommentsController it "does something" do get :index, { user_id: "1", post_id: "1" } end end
... then everything is fine again.
So my question is that this was not the case in Rails 3, can I now trust the validation of the controller actions to fully validate / verify my routes in Rails 4+? Or is there an added advantage when testing routes, as well as more? Is there perhaps some other angle that covers route tests that are not verified by controller control tests? (Note: I am not asking for the opinion that it is good to test, I am asking for functional differences between the route integration tests and the controller actions tests regarding route requirements).
Also, I couldn't find a specific link to this behavior change in the Rails 4 release notes (or in Minitest), so I wonder why this change was made in the first place. I don’t think it’s bad, I think it’s good, but I feel strange not seeing that he is mentioned in the changelog somewhere. And I thought that the half point of the get|patch|post|delete methods should free you from having to think about which parameters are needed for routing in the first place.
For completeness, here is a route test that I would use for this:
describe "CommentsController Route Integration Test" do let(:default_options) { { controller: "api/v2/comments", user_id: "1", posts_id: "1", format: :json } } it "#index" do assert_routing "/api/v2/users/1/posts/1/comments", default_options.merge(action: "index") end end
UPDATE
I was looking at the ActionDispatch code for the answer ... the only thing I can see so far is that the url_for has changed a lot from Rails 3 and that the ActionController :: UrlGenerationError class itself has been added to Rails 4. So it’s possible that these new, more stringent routing requirements are a random change to the decoupling of ActionView and ActionController.