ActionController::UrlGenerationError: No route matches when trying to test the controller - ruby-on-rails

I'm getting an ActionController::UrlGenerationError: No route matches (:action => "edit", :controller => "goals") error, when I'm trying to test the goals controller
Here is my goals_controller_test.rb
require 'test_helper'
class GoalsControllerTest < ActionController::TestCase
test "should be redirected when not logged in" do
get :new
assert_response :redirect
assert_redirected_to new_user_session_path
end
test "should render the new page when logged in" do
sign_in users(:guillermo)
get :new
assert_response :success
end
test "should get edit" do
get :edit
assert_response :success
end
test "should get show" do
get :show
assert_response :success
end
end
This is my routes.rb
Rails.application.routes.draw do
devise_for :users
authenticated :user do
root 'du#dashboard', as: "authenticated_root"
end
resources :goals
root 'du#Home'
end
My goals_controller.rb
class GoalsController < ApplicationController
before_filter :authenticate_user!, only: [:new]
def new
end
def edit
end
def show
end
private
def find_user
#user = User.find(params[:user_id])
end
def find_goal
#goal = Goal.find(params[:id])
end
end
I find it weird that if I use get 'goals/edit' instead of resources :goals the test passes.
Thank you very much for any guideline.

When you use resources :goals Rails generates for you the following routes (RESTful):
goals GET /goals(.:format) goals#index
POST /goals(.:format) goals#create
new_goal GET /goals/new(.:format) goals#new
edit_goal GET /goals/:id/edit(.:format) goals#edit
goal GET /goals/:id(.:format) goals#show
PATCH /goals/:id(.:format) goals#update
PUT /goals/:id(.:format) goals#update
DELETE /goals/:id(.:format) goals#destroy
As you can see, to hit the edit action /goals/:id/edit you need to pass an :id. That way, in your controller you'll be able to find the record by the given :id => Goal.find(params[:id]). So, in your tests you need to pass this :id, something like:
get :edit, id: 1 # mapping to /goals/1/edit
If you manually add this route get 'goals/edit', it works because it maps directly to /goals/edit (NOTE there is no :id).
Btw, I recommend you to review the official Routing guides: http://guides.rubyonrails.org/routing.html

#goal = Goal.create(your params here) or use factory girl gem or fixtures
you should pass id get :edit ,id: #goal
useful article

Related

Rspec controller action not found

test is failing becasue it says the action does not exist, when it clearly does. Is it becasue it is a nested route? Any thoughts?
Update:
I moved resources :orders outside of the nested route and tests passed. So it has something to do with it being nested.
OrderController
def index
if current_printer
#orders = Order.all
#printer = Printer.find(params[:printer_id])
end
if current_user
#orders = Order.where(user_id: params[:user_id])
end
end
OrdersController Spec
require 'rails_helper'
RSpec.describe OrdersController, :type => :controller do
describe "unauthorized user" do
before :each do
# This simulates an anonymous user
login_with_user nil
binding.pry
end
it "should be redirected back to new user session" do
get :index
expect( response ).to redirect_to( new_user_session_path )
end
end
end
Routes
resources :users, only: [:index, :show] do
resources :orders
end
Error
Failures:
1) OrdersController unauthorized user should be redirected back to new user session
Failure/Error: get :index
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"orders"}
When testing controllers that have nested routes you must pass in a hash of the url params.
for example my routes looked like this
user_orders GET /users/:user_id/orders(.:format) orders#index
so in my test I passed in a hash with user_id
get :index, { user_id: 1 }
Tests passing :)

New Controller - No Route Matches update, edit, show or destroy

I'm having some difficulty getting all the RESTful routes to be setup correctly. I've taken the simplest of simple steps in my app so far.
Create new rails app
Create new controller with RESTful actions
Add resources to routes.rb
And yet 4 out of my 7 actions fail the default tests. Can anyone please explain why?
rails generate controller Employees new create update edit destroy index show
And here's the corresponding controller, employees_controller.rb
class EmployeesController < ApplicationController
def new
end
def create
end
def update
end
def edit
end
def destroy
end
def index
end
def show
end
end
Now I add the resources to routes.rb
Rails.application.routes.draw do
resources :employees
end
All the routes seem to be there, based on the output of rake routes
Prefix Verb URI Pattern Controller#Action
employees GET /employees(.:format) employees#index
POST /employees(.:format) employees#create
new_employee GET /employees/new(.:format) employees#new
edit_employee GET /employees/:id/edit(.:format) employees#edit
employee GET /employees/:id(.:format) employees#show
PATCH /employees/:id(.:format) employees#update
PUT /employees/:id(.:format) employees#update
DELETE /employees/:id(.:format) employees#destroy
But now when I run the default tests, I get 4 errors:
# Running:
.EEEE..
Finished in 0.267712s, 26.1475 runs/s, 11.2061 assertions/s.
1) Error:
EmployeesControllerTest#test_should_get_update:
ActionController::UrlGenerationError: No route matches {:action=>"update", :controller=>"employees"}
test/controllers/employees_controller_test.rb:15:in `block in <class:EmployeesControllerTest>'
2) Error:
EmployeesControllerTest#test_should_get_destroy:
ActionController::UrlGenerationError: No route matches {:action=>"destroy", :controller=>"employees"}
test/controllers/employees_controller_test.rb:25:in `block in <class:EmployeesControllerTest>'
3) Error:
EmployeesControllerTest#test_should_get_show:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"employees"}
test/controllers/employees_controller_test.rb:35:in `block in <class:EmployeesControllerTest>'
4) Error:
EmployeesControllerTest#test_should_get_edit:
ActionController::UrlGenerationError: No route matches {:action=>"edit", :controller=>"employees"}
test/controllers/employees_controller_test.rb:20:in `block in <class:EmployeesControllerTest>'
7 runs, 3 assertions, 0 failures, 4 errors, 0 skips
Lastly, here is the contents of employees_controller_test.rb. As I said, these are the default tests auto-created by Rails upon generation of the controller.
require 'test_helper'
class EmployeesControllerTest < ActionController::TestCase
test "should get new" do
get :new
assert_response :success
end
test "should get create" do
get :create
assert_response :success
end
test "should get update" do
get :update
assert_response :success
end
test "should get edit" do
get :edit
assert_response :success
end
test "should get destroy" do
get :destroy
assert_response :success
end
test "should get index" do
get :index
assert_response :success
end
test "should get show" do
get :show
assert_response :success
end
end
according to dimakura's answer you have to change some routes in your test
the update method is a put (or a patch for partial changes in rails4)
test "should get update" do
put :update
assert_response :success
end
and for your edit, delete and show routes, the id is missing
test "should get edit" do
get :edit, id: 2
assert_response :success
end
Your controller test probably looks like:
class EmployeesControllerTest < ActionController::TestCase
test "should get create" do
get :create
assert_response :success
end
# other tests not shown
end
You should change it to this:
class EmployeesControllerTest < ActionController::TestCase
test "should get create" do
post :create
assert_response :success
end
# other tests should be changed accordingly
end
Use patch or put method for update, and delete for delete actions.

No route error when GETting root_path, but only in some of my tests

I have a root_path defined in routes.rb and I call get root_path in other tests, but for some reason, in test/controllers/application_controller_test.rb, I get this error when calling get root_path:
ApplicationControllerTest#test_should_get_index_when_not_logged_in:
ActionController::UrlGenerationError: No route matches {:action=>"/", :controller=>"application"}
test/controllers/application_controller_test.rb:10:in `block in <class:ApplicationControllerTest>'
Here's routes.rb
Rails.application.routes.draw do
root 'application#index'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:edit, :new, :create, :update]
resources :lessons, only: [:show, :index] do
resources :pre_lesson_surveys, shallow: true,
except: :destroy
end
end
Here's application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
def index
render 'admin_home_page' if admin?
render 'user_home_page' if logged_in?
#user = User.new unless logged_in?
end
end
and here's one of the tests
test "should get index when not logged in" do
get root_path
assert_response :success
assert_not is_logged_in?
assert_template 'application/index'
end
I'm sure I'm just doing something stupid, but I can't put my finger on it
If you want to make sure that the index template gets rendered on a request to your root path, a request spec may be appropriate:
spec/requests/application_requests_spec.rb:
describe "Test Root Path" do
it 'successfully renders the index template on GET /' do
get "/"
expect(response).to be_successful
expect(response).to render_template(:index)
end
end
If you want to make sure that the index template gets rendered on a request to the index action of your ApplicationController, a controller spec may be appropriate.
spec/controllers/application_controller_spec.rb:
describe ApplicationController do
describe "GET index" do
it "successfully renders the index template" do
expect(controller).to receive(:index)
get :index
expect(response).to be_successful
expect(response).to render_template(:index)
end
end
end

ActionController::UrlGenerationError - with route defined and action in controller, still getting error for no route

I'm getting the following error in RSpec when running my schools_controller_spec.rb test:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"schools"}
What's puzzling me is that I have the routes configured, and the action defined in the appropriate controller. I'm not getting this error for other tests in the spec, such as 'GET #index', etc. Running Rails 4.2 with RSpec/Capybara.
Here's the routes.rb:
Rails.application.routes.draw do
root to: 'pages#home', id: 'home'
resources :users
resources :schools
resource :session, only: [:new, :create, :destroy]
match '/home', to: 'pages#home', via: 'get', as: 'home_page'
end
rake routes returns:
schools GET /schools(.:format) schools#index
POST /schools(.:format) schools#create
new_school GET /schools/new(.:format) schools#new
edit_school GET /schools/:id/edit(.:format) schools#edit
school GET /schools/:id(.:format) schools#show
PATCH /schools/:id(.:format) schools#update
PUT /schools/:id(.:format) schools#update
DELETE /schools/:id(.:format) schools#destroy
There's the route defined on the fifth line, as schools#show.
The schools_controller.rb:
class SchoolsController < ApplicationController
before_action :require_signin
before_filter :admin_only, except: :index, :show
def index
#schools = School.all
end
def show
# code pending
end
private
def admin_only
unless current_user.admin?
redirect_to :back, alert: "Access denied."
end
end
end
The link to the individual school seems to be properly defined in the view helper (_school.html.haml):
%li#schools
= link_to school.name, school
= school.short_name
= school.city
= school.state
and looking at the front-end HTML confirms it's working correctly. I can see, for example: Community College of the Air Force. When I click that link the page shows the following in the debug dump:
--- !ruby/hash:ActionController::Parameters
controller: schools
action: show
id: '1'
Finally, for good measure, here's the spec file (schools_controller_spec.rb):
require 'rails_helper'
describe SchoolsController, type: :controller do
# specs omitted for other actions
describe 'GET #show' do
context "when not signed in" do
it "returns a 302 redirect code" do
get :show
expect(response.status).to eq 302
end
it "redirects to the signin page" do
get :show
expect(response).to redirect_to new_session_path
end
end
context "when signed in as user" do
before :each do
#user = double(:user)
allow(controller).to receive(:current_user).and_return #user
#school = create(:school)
end
it "assigns the school to the #school variable" do
get :show
expect(assigns(:school)).to eq #school
end
end
end
end
The route appears in rake routes. The method is defined in the appropriate controller. There don't appear to be any silly naming errors (e.g. plural/singular). The spec doesn't appear to have any issues routing GET #index or other routes for example. Everything works exactly as expected in the browser.
So why do I keep getting the "no route matches" error when I run my controller spec?
This is because the show action is expecting an id which you currently aren't passing. Replace:
get :show
With this:
get :show, id: school.id
The above assumes you have a school variable, perhaps a let in a before block?
let(:school) { create(:school) }

Rails 4: testing GET request on a namespaced controller

I have a failing test that I'm struggling to understand. I have a controller class Users::QueriesController < ApplicationController at app/controllers/users/queries_controller.rb which has a show action, and a corresponding namespaced route:
namespace :users do
resources :queries
end
I also have a test at test/controllers/users/queries_controller_test.rb:
require 'test_helper'
class Users::QueriesControllerTest < ActionController::TestCase
test "accessing :show action" do
get :show
assert_response :success
end
end
Running this test results in ActionController::UrlGenerationError: No route matches {:controller=>"users/queries", :action=>"show"}.
Running rake routes includes this line: users_query GET /users/queries/:id(.:format) users/queries#show.
What's going wrong here? I'm using Rails 4.0.0.
I think you need to provide an id to the show action
test "accessing :show action" do
get :show, {:id => 1}
assert_response :success
end
That's the right way prior to rails 4.
Please have a try, and let me know the outcome.

Resources