Oatmeal
Oatmeal

Reputation: 759

How to test custom routes in controller with rspec

I have defined a custom route in routes.rb

get "packages/city/:location_id",  to: "packages#index"

In controller_spec.rb,

get :index

gives this error,

ActionController::UrlGenerationError:
   No route matches {:action=>"index", :controller=>"packages"}

How to explicitly specify the custom routes in controller specs?

Upvotes: 13

Views: 12847

Answers (4)

Denis S Dujota
Denis S Dujota

Reputation: 611

2019

Was tackling this same error on my controller specs. Tried accepted and follow up solutions, but they also did not work, either led to no method error or persisted the no route match error.

Directly defining the route like in the accepted solution also did not satisfy the errors.

After much searching and some keyboard smashing tests pass.

Things to note

  • controller is for polymorphic resource
  • routes are nested within the resources :location, only[:index, :show] do ... end
  • this is API routes, so JSON only

Solution

let(:location) do
    create(:location)
  end


shared_examples("a user who can't manage locations") do
    describe 'GET #index' do
      it 'denies access' do

        get :index, params:{location_id: location.locationable.id, format: :json}
        expect(response).to have_http_status :unauthorized
      end
    end
end

So in the end it was a combination of both solutions, but had to put them in the params hash or else it would throw name/no method or route errors

Conclusion

  • references to the association must be in the params hash
  • even if controller responds_to :json, it will throw errors no route errors
  • must include a data hash in your request or no route match errors will appear

Hope this helps,

Cheers!

Upvotes: 2

zarathustra
zarathustra

Reputation: 2080

2017

I tried the solutions above but they did not work. I got:

ArgumentError:
   unknown keyword: location_id

It seems that RSpec now requires a params parameter. The corresponding call would look like this:

get(:index, params: { location_id: 123 })

Upvotes: 10

equivalent8
equivalent8

Reputation: 14227

it's because you are not passing location_id

the route is defined to match:

/packages/city/:location_id

so in order to comply with it you need to do something like

get :index, location_id: 1234

Had the same issue with Controller spec:

# rake routes | grep media_order
teacher_work_media_orders PATCH /teacher/works/:work_id/media_orders(.:format)  teacher/media_orders#update

when I did:

# spec/controller/teacher/media_orders_controller
patch :update data: {}

I got

 Failure/Error: patch :update
 ActionController::UrlGenerationError:
   No route matches {:action=>"update", :controller=>"teacher/media_orders"}

but when I did

patch :update, work_id: 1234, data: {}

that worked

Upvotes: 2

mgrim
mgrim

Reputation: 1302

Perhaps it helps if you declare your route like this?

get "packages/city/:location_id" => "packages#index"

Remember to provide a location_id param in specs, e.g. get :index, location_id: 1.

Upvotes: 15

Related Questions