How to test a controller action that does not exist?
Asked Answered
P

1

2

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.

Purpleness answered 21/8, 2013 at 12:26 Comment(1)
As you've said, routing specs would be enough.Drape
P
3

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.

Purpleness answered 21/8, 2013 at 13:43 Comment(1)
If you add a constaint on id in your routes it will work: constraints(id: /\d+/)Pomegranate

© 2022 - 2024 — McMap. All rights reserved.