I create all the routes of my program manually and so do with my rspec tests of course. Generally, my routes and tests work fine, but i have a problem with the test for my characters controller. The route is :
scope :path => '/characters', :controller => :characters do
get '/' => :show, :as => 'user_character'
end
The /characters works fine when tested with my browser. Everything seems fine. But, the test :
require 'spec_helper'
require 'devise/test_helpers'
describe CharactersController do
login_user
describe "when it GETS 'show'" do
it "should render the template and be successful" do
get :show
response.should render_template(:show)
response.should be_success
end
end
end
Fails with the error :
1) CharactersController when it GETS 'show' should render the template and be successful
Failure/Error: get :show
ActionController::RoutingError:
No route matches {:controller=>"characters", :action=>"show"}
# ./spec/controllers/characters_controller_spec.rb:9
All my controllers have similar tests that work fine. Why does this not work ?
IMPORTANT EDIT :
Just saw that if i turn Spork off, the test passes ! Why is this happening ? Does Spork need to be restarted every time a new test is added ?
You have to restart spork when changing routes.
Or put this in your spec_helper.rb:
Spork.each_run do
ApplicationName::Application.reload_routes!
end
See also "Speedy Test Iterations for Rails 3 with Spork and Guard"
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 have a custom route for devise:
devise_scope :user do
get '/login' => "devise/sessions#new", :as => :new_user_session
get '/logout' => 'devise/sessions#destroy',
...
I want to make sure that when the request /login is called, that it gets correctly routed to devise and that the response is successful.
How do you test for custom routing and a successful request?
If you're using the built-in TestUnit to test, check out the Rails Guide on testing controllers.
If you're using Rspec, check out the Rspec Github Page for information on testing controllers.
It depends on you testing suite, personally I use RSpec + Capybara for my Rails projects.
If you don't have a testing suite yet I highly recommend this guide.
http://everydayrails.com/2012/03/12/testing-series-intro.html
In this particular instance, I'd say you want two tests. One for the routing and one for a successful request. Using rspec, this will look something like:
#spec/routing/devise_routing_spec.rb
require 'spec_helper'
describe "Devise Routes" do
it "should route the login correctly" do
{:get => "login"}.should route_to(controller: "devise/sessions", action: "new")
end
end
and
#spec/controllers/devise/session_controller_spec.rb
require 'spec_helper'
describe Devise::Sessions do
it "should be successful with a login request" do
get "new"
response.should be_success
end
end
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
In config/routes.rb:
match 'app_config/:version' => "application#appconfig"
test/functional/application_controller_test.rb:
require 'test_helper'
class ApplicationControllerTest < ActionController::TestCase
test "app config" do
get "/app_config/v2"
assert_response :success
end
end
rake test:
1) Error:
test_app_config(ApplicationControllerTest):
ActionController::RoutingError: No route matches {:controller=>"application", :action=>"/app_config/v2"}
but $ curl localhost:3000/app_config/v2 works, and returns the response I expect, and rake routes shows the route as expected. Any idea what's going on, or how to investigate further? This is basically the only code in the project.
The get method does not take a route. It takes an action name and a parameter's hash.
If you want to test the action, your tests should look like this:
test "for success" do
get :appconfig, :version => "v2"
assert_response :success
end
If you want to test routing there is a tutorial here in the documentation.
test "should route to appconfig" do
assert_routing '/app_config/v2', { :controller => "application", :action => "appconfig", :version => "v2" }
end
I have simplified an issue I am having to the following
I have a route that looks like this
namespace :client do
resources :thing, :only => [:index]
end
and the simple rspec test
describe Client::ThingController do
describe "GET 'index'" do
it "returns http success" do
get 'index'
response.should be_success
end
end
end
However what I'd like to do is alter the url I use to access the resource from
/client/thing.json
to
/api/client/v1/thing.json
1) How do I update my routes and rspec?
If I then wanted to parameterise the uri such that I could extract the api_version
/api/client/[api_version]/thing.json
2) How would this effect my routes and simple rspec test?
I'd previously tried what #Mori had suggested before I had posted but without having the multiple routes as proposed, I should have mentioned that in the original post.
What I eventually got that worked is:
1) In routes.rb I added
match "api/client/:api_version/thing" => 'client/thing#index'
NOTE: The missing leading '/' ie match "/api/... => match "api/... it seems to make all the difference to rspec.
2) And in my rspec thing_controller_spec.rb I now have this
describe Client::ThingController do
describe "GET 'index'" do
it "returns http success" do
get 'index', :api_version => 'v1'
response.should be_success
end
end
end
I was close before but it was the leading '/' in routes.rb that broke me even though I could navigate to the url in a browser.