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.
Related
I'm trying to write a controller test and Rspec isn't finding routes that I know exist and work fine on a development server.
In my routes I have a catch-all route that should redeirect to a generic controller if someone goes to a route that isn't predefined.
routes.rb
namespace :tools do
match '*unmatchedpath' => "generic#show", :via => :get
end
generic_controller.rb
def show
# do stuff
end
generic_controller_spec.rb
require 'spec_helper'
describe Tools::GenericController do
describe 'GET show' do
it 'does stuff' do
get :show
end
end
Here is the error I get from rspec when I run the test above
1) Tools::GenericController GET show does stuff
Failure/Error: get :show
ActionController::RoutingError:
No route matches {:controller=>"tools/generic", :action=>"show"}
All routes work as expected on my development server so I'm not sure why Rspec isn't finding the route.
Try:
get '*unmatchedpath' => 'tools/generic#show'
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
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.
I have my brands controller in app/controllers/merchant/brands_controller.rb
I'm trying to write a functional test for it. I've defined test class as
require 'test_helper'
class Merchant::BrandsControllerTest < ActionController::TestCase
include Devise::TestHelpers
setup do
#user = users(:one)
sign_in #user
#brand= brands(:one)
end
test "should get index" do
get :index
assert_response :success
end
end
but the tests throw an error saying
ActionController::RoutingError: No route matches {:controller=>"merchant/brands", :action=>"new"}
Why is it using 'merchant/brands' as controller name?
Or can I specify custom route to make a request to 'new' method?
My routes look like this
namespace :merchant do
resources :accounts do
resources :brands
end
end
I
It seems you forgot the accounts part of your route.
Try with
class Merchant::Accounts::BrandsControllerTest
I'm trying to test a controller that is inside an engine my application is using. The spec is not within the engine, but in the application itself (I tried to test within the engine but also had problems).
My engine has the following routes.rb:
Revision::Engine.routes.draw do
resources :steps, only: [] do
collection { get :first }
end
end
The engine is mounted on the application routes.rb normally:
mount Revision::Engine => "revision"
When I run rake routes, at the last lines I get:
Routes for Revision::Engine:
first_steps GET /steps/first(.:format) revision/steps#first
root / revision/steps#first
On my engine's controller (lib/revision/app/controllers/revision/steps_controller.rb), I have:
module Revision
class StepsController < ApplicationController
def first
end
end
end
On Rspec, I test this controller with:
require 'spec_helper'
describe Revision::StepsController do
it "should work" do
get :first
response.should be_success
end
end
Then when I run this spec, I get:
ActionController::RoutingError:
No route matches {:controller=>"revision/steps", :action=>"first"}
To be sure that the route doesn't really exist, I added this to the spec:
before do
puts #routes.set.to_a.map(&:defaults)
end
And the result is this:
[...]
{:action=>"show", :controller=>"devise/unlocks"}
{:action=>"revision"}
It has only the :action parameter.
What may be wrong?
When you're trying to test an engine's controllers, you need to specify what route set you want the controller test to use, otherwise it will run it against the main app's. To do that, pass use_route: :engine_name to the get method.
require 'spec_helper'
describe Revision::StepsController do
it "should work" do
get :first, use_route: :revision # <- this is how you do it
response.should be_success
end
end