Search code examples
ruby-on-railsruby-on-rails-4rspecrspec-rails

How to write Spec tests for routes - Rails 4


I'm trying to write a test for SessionsController and I wrote the following:

I'm using Spec 3.3

    RSpec.describe SessionsController, type: :controller do

        describe SessionsController do

            describe "POST create" do 

                it "sign in should have a valid route" do
                    post('/api/signin').should route_to('api/sessions#create')
                end

            end

        end

    end

This app is to work mostly as an API, so for now, there's no need for views.

In my routes I have the following:

match     '/api/signin',                          to: 'api/sessions#create',

Yet the test is not passing.

Any suggestions?

EDIT: The errors:

rspec ./spec/controllers/sessions_controller_spec.rb:27 # SessionsController SessionsController POST create sign in should have a valid route
rspec ./spec/controllers/sessions_controller_spec.rb:31 # SessionsController SessionsController POST create creates a new session

EDIT2: Added full test code


Solution

  • You must specify type: :routing and use assert_routing which has the benefice to test your route in 2 ways (route generation and route matching)

    I make my answer general, so other people can take info from it, please adapt to your case

    describe MyController, type: :routing do
      it 'routing' do
        # This is optional, but also a good reminder to tell me when I add a route
        #   and forgot to update my specs.
        #   Please see bellow for the helper definition
        expect(number_of_routes_for('my_controller')).to eq(8)
    
        # Then test for the routes, one by one
        assert_routing({method: :get, path: '/my_controller'},   {controller: 'my_controller', action: 'index'})
        assert_routing({method: :get, path: '/my_controller/1'}, {controller: 'my_controller', action: 'show', id: '1'})
        # ... And so on, for each route
      end
    end
    

    Note: If get errors with assert_routing (I guess it will be the case with match, but I can't remember) then have a look at assert_generates and assert_recognizes


    And the number_of_routes_for helper

    def number_of_routes_for(controller)
      Rails.application.routes.routes.to_a.select{ |r| r.defaults[:controller] == controller }.count
    end