Jensky
Jensky

Reputation: 917

RSpec "No route matches" error but they match

I have tests like those:

RSpec.describe RestaursController, :type => :controller do

  context "GET /restaurs/:id" do
    before do 
      @rest = FactoryGirl.create :restaur
    end

    context "resource exists" do
      subject { get "restaurs/#{@rest.id}"}
      it { expect(subject).to render_template(:show) }
    end

    context "resource doesn't exists" do
      subject { get "restaurs/#{@rest.id + 1}" }
      it { expect(subject).to redirect_to(:root) }
    end
  end
end

When I run those tests RSpec says:

 Failure/Error: subject { get "restaurs/#{@rest.id}"}
 ActionController::UrlGenerationError:
   No route matches {:action=>"restaurs/7", :controller=>"restaurs"}

But I think my routes are OK. Look on rake routes log

      Prefix Verb   URI Pattern                  Controller#Action
    restaurs GET    /restaurs(.:format)          restaurs#index
             POST   /restaurs(.:format)          restaurs#create
 new_restaur GET    /restaurs/new(.:format)      restaurs#new
edit_restaur GET    /restaurs/:id/edit(.:format) restaurs#edit
     restaur GET    /restaurs/:id(.:format)      restaurs#show
             PATCH  /restaurs/:id(.:format)      restaurs#update
             PUT    /restaurs/:id(.:format)      restaurs#update
             DELETE /restaurs/:id(.:format)      restaurs#destroy
        root GET    /                            restaurs#index

Have you got any ideas? What is the problem? Maybe it is about RSpec syntax or something like that?

Upvotes: 1

Views: 507

Answers (1)

user229044
user229044

Reputation: 239230

That isn't how you get actions in a controller test. The argument to get is the name of the action, not a routable path. Routing isn't involved in testing controllers, and neither is rake routes.

You're giving it the action name "restaurs/7", which obviously isn't the real name of a method on your controller. Instead, you should be using get :show to invoke the actual method "show" on your controller, and then passing a hash of parameters:

get :show, id: @rest.id + 1

Similarly, you would use get :index, not get "/", and you would use get :edit, id: ..., not get "/restaurs/#{...}/edit". It's the actual method your meant to test on your controller, not whether a route actually leads you to the correct method.

As a related aside, your opening context is out of place. You shouldn't be using GET /restaurs:/:id as a context. Routing isn't involved here. Just test the method names.

Upvotes: 2

Related Questions