Freelancing Gods 2014

God
13 Dec 2007

Rspec'ing controllers

I’m always trying to find a better way to write specs for my Rails apps with RSpec – it took a while for me to be comfortable with writing model specs, but just recently, I’ve developed a style of controller specs that I feel work well for me.

While it’s not too hard to write methods that automate some of the repetitive side of things, it can be hard to do so in a manner that fits RSpec’s DSL – but I’ve found the key to (my current style of) controller specs is shared behaviours. An example of a few actions from the news controller at ausdwcon.org:

describe NewsController, "index action" do
  before :each do
    @method = :get
    @action = :index
    @params = {}
  end
  
  it_should_behave_like "Public-Access Actions"
  
  it "should paginate the results" do
    @news = []
    News.stub_method(:paginate => @news)
    
    get :index
    
    News.should have_received(:paginate)
    assigns[:news].should == @news
  end
  
  it "should set the title to 'News'" do
    News.stub_method(:paginate => [])
    
    get :index
    
    assigns[:title].should == "News"
  end
end

describe NewsController, "new action" do
  before :each do
    @method = :get
    @action = :new
    @params = {}
  end
  
  it_should_behave_like "Admin-Only Actions"
  
  it "should set the title to 'News'" do
    controller.current_user = User.stub_instance(:admin? => true)
    
    get :new
    
    assigns[:title].should == "News"
  end
end

You can find the full spec for the controller on pastie.caboo.se. The shared behaviors – ‘Public-Access Actions’ and ‘Admin-Only Actions’ – are (at least for the moment) kept in my spec_helper.rb file – a sample of which is below:

describe "Admin-Only Actions", :shared => true do
  it "should not be accessible without authentication" do
    @controller.current_user = nil
    
    send @method, @action, @params
    
    response.should be_redirect
    response.should redirect_to(new_session_url)
  end
  
  it "should not be accessible by a normal user" do
    @controller.current_user = User.stub_instance(:admin? => false)
    
    send @method, @action, @params
    
    response.should be_redirect
    response.should redirect_to(new_session_url)
  end
  
  it "should be accessible by an admin user" do
    @controller.current_user = User.stub_instance(:admin? => true)
    
    send @method, @action, @params
    
    response.should_not redirect_to(new_session_url)
  end
end

Firstly – the not so nice stuff: the use of instance variables to communicate the method, action and parameters of requests to the shared behaviours. It’s not ideal, and apparently there’s plans to add arguments to the it_should_behave_like method, but for the moment it does the job.

I’m using Pete Yandell’s NotAMock for my stubbing – albeit with a few modifications of my own (which may make it back into the plugin itself at some point). I also use my own ActiveMatchers – but that’s more focused on models. It’s also not really feature-complete, but if you like what it offers, feel free to use it.

Oh, and the main caveat? This is my current way of spec’ing controllers – and it’s vastly better than the minimal specs I was writing before this – but it may/will change. I don’t even know if my style is ‘best practice’ – I’m putting them online to get feedback and provoke discussion. So please feel free to critique.

Comments

1 response to this article

24 Apr 2009
diwakar said:

If you have mentioned the controller it would have been more helpful

Leave a Comment

Comments are formatted using Textile. Please be respectful of others when posting comments. Be nice.

RssSubscribe to the RSS feed

Related Links

Related Posts

About Freelancing Gods

Freelancing Gods is written by , who works on the web as a web developer in Melbourne, Australia, specialising in Ruby on Rails.

In case you're wondering what the likely content here will be about (besides code), keep in mind that Pat is passionate about the internet, music, politics, comedy, bringing people together, and making a difference. And pancakes.

His ego isn't as bad as you may think. Honest.

Here's more than you ever wanted to know.

Ruby on Rails Projects

Other Sites

Creative Commons Logo All original content on this site is available through a Creative Commons by-nc-sa licence.