Spec the Application Controller application.rb

How would I go about writing specs for methods in the Application
Controller:

I’m thinking of simple methods that do authentication, through before
filters or for example how might I spec this method in an
application_spec.rb?

def store_location
session[:return_to] = request.request_uri
end

The trouble is I’m not generating a request object as the methods are to
be used by all controllers… I’ve tried stubbing…

request = mock_model(URI::HTTP, :request_uri => “something”)

…or setting the variable in the spec itself…

request.response_uri = “something”

…but I can’t seem to get the approach right!

On Mon, Apr 21, 2008 at 8:27 AM, Andy C. [email protected]
wrote:

The trouble is I’m not generating a request object as the methods are to
be used by all controllers… I’ve tried stubbing…

request = mock_model(URI::HTTP, :request_uri => “something”)

…or setting the variable in the spec itself…

request.response_uri = “something”

…but I can’t seem to get the approach right!

Hey Andy,

You can define a controller method on the fly in order to test this
out. I just did a quick experiment to demonstrate it…obviously
modify to suit your needs.

application_controller_spec.rb:
require File.dirname(FILE) + ‘/…/spec_helper’

describe “a before_filter” do
class FooController < ApplicationController
def index; render :text => “foos”; end
end
controller_name :foo

it “should work” do
get :index
assigns[:assigned].should_not be_blank
end
end

application.rb:
class ApplicationController < ActionController::Base
before_filter :set_assigned

def set_assigned
@assigned = “yay”
end
end

Pat M. wrote:

You can define a controller method on the fly in order to test this
out. I just did a quick experiment to demonstrate it…obviously
modify to suit your needs.

Thanks Pat.

I think I’m confusing two issues.

  1. How to test before filters for something like authentication
  2. How to test functions provided in the application controller

I’m not putting the before filter in the application.rb, I’m likely to
be using it to protect various actions in the app.

Is there a way to to call methods directly within the application.rb,
spec them there and then sub for functionality in the other controllers?

Andy

PS Your ‘controller spec’ blog post was the ‘light-going-on-in-my-head’
moment for RSpec. Thanks for that!

Pat M. wrote:

You can still use the technique that I showed, you would just call
before_filter in the fake controller. That would allow you to specify
and implement the filter in isolation.

Aha! Success, although I needed to add in a little Route fixing to make
it work.

application_spec.rb:

describe ApplicationController, “storing locations” do
class FooController < ApplicationController
before_filter :assign_var
def index; render :text => “foos”; end
end
controller_name :foo

before(:each) do
ActionController::Routing::Routes.draw do |map|
map.resources :foo
end
end

it “should assign the current user” do
get :index
assigns[:var].should_not be_blank
end
end

application.rb:

class ApplicationController < ActionController::Base
def assign_var
@var = “Quantum Leap Rocks”
end
end

Hooray.

On Tue, Apr 22, 2008 at 11:19 PM, Andy C. [email protected]
wrote:

  1. How to test functions provided in the application controller

I’m not putting the before filter in the application.rb, I’m likely to
be using it to protect various actions in the app.

You can still use the technique that I showed, you would just call
before_filter in the fake controller. That would allow you to specify
and implement the filter in isolation.

Is there a way to to call methods directly within the application.rb,
spec them there and then sub for functionality in the other
controllers?

No to the first part, unfortunately. Rails’ controller design isn’t
particularly test-friendly.

As far as using them in other controllers, you can just use the real
filter implementation if you want, or stub them if you prefer.

Pat

This bit however, replaces your other routes, so you cannot use them in
your tests

before(:each) do
ActionController::Routing::Routes.draw do |map|
map.resources :foo
end
end

Is there a sensible way to append to the routes.rb that I’m missing?

Andy

Do this…

after do
eval IO.read(RAILS_ROOT + “/config/routes.rb”)
end

Zach