Search code examples
ruby-on-railstestingrspeccontrollers

Test controllers without going through routing


I'm trying to test my controller's action chain in isolation. Specifically, I want to ensure my desired behavior is applied to all my controller's actions. For example, test that all my actions require authentication:

context "when not authenticated" do

  # single case
  describe "GET index" do
    it "responds with 401" do
      get :index
      response.code.should be(401)
    end
  end

  # all of them...
  described_class.action_methods.each do |action|
    ['get', 'put', 'post', 'delete', 'patch'].each do |verb|
      describe "#{verb.upcase} #{action}" do
        it "responds with 401" do
          send verb, action
          response.code.should == "401"
        end
      end
    end   
  end

end

I expected this to work but it doesn't. I get some ActionController::RoutingErrors. This is because some of my routes require params and in some cases I'm not supplying them (like when I call post :create). I get that. But what I don't understand is: why should it matter!?

For these tests routing is a separate concern. I care about my action chains, not my requests (that's what I have routing specs and request specs for). I shouldn't need to concern myself with my route constraints at this level.

So my question: Is there a way to test just the action chain without simulating a request?

EDIT: some research

It looks like routes are being exercised in TestCase#process. Is this necessary?


Solution

  • One work around is to loosen the routing engine's constraints. This doesn't bypass routing, but it does make it easier to work with for testing.

    Add something like the following to your specs:

    before(:all) do
      Rails.application.routes.draw { match ':controller(/:action)' }
    end
    after(:all) do
      Rails.application.reload_routes!
    end
    

    While not strictly an answer to the question, it might be a good enough work around.