How to test a controller action that does not exist?

1.1k views Asked by At

There are only two actions accessible in the ProductsController:

# /config/routes.rb
RailsApp::Application.routes.draw do
  resources :products, only: [:index, :show]
end

Tests are set up accordingly:

# /spec/controllers/products_controller_spec.rb
require 'spec_helper'

describe ProductsController do

  before do
    @product = Product.gen
  end

  describe "GET index" do
    it "renders the index template" do
      get :index
      expect(response.status).to eq(200)
      expect(response).to render_template(:index)
    end
  end

  describe "GET show" do
    it "renders the show template" do
      get :show, id: @product.id
      expect(response.status).to eq(200)
      expect(response).to render_template(:show)
    end
  end

end

How would you test that the other CRUD actions are not accessible? This might change in the future so the tests will ensure any configuration change will be noticed.
I found the be_routable matcher which looks promising to cover the test case.


I recommend this post by Dave Newton which describes when and why to test controller actions.

1

There are 1 answers

1
JJD On

Here is what I came up with:

context "as any user" do
  describe "not routable actions" do
    it "rejects routing for :new" do
      expect(get: "/products/new").not_to be_routable
    end
    it "rejects routing for :create" do
      expect(post: "/products").not_to be_routable
    end
    it "rejects routing for :edit" do
      expect(get: "/products/#{@product.id}/edit").not_to be_routable
    end
    it "rejects routing for :update" do
      expect(put: "/products/#{@product.id}").not_to be_routable
    end
    it "rejects routing for :destroy" do
      expect(delete: "/products/#{@product.id}").not_to be_routable
    end
  end
end

However one test fails:

Failure/Error: expect(get: "/products/new").not_to be_routable
  expected {:get=>"/products/new"} not to be routable, 
  but it routes to {:action=>"show", :controller=>"products", :id=>"new"}

Please feel free to add your own solution if you follow a totally different approach to test non-existing routes.