Some prettifications for RSpec Rails.
sudo gem install rspec-rails-ext
Then, within your spec/spec_helper.rb
require 'rspec_rails_extensions'
If you try to call ActiveRecord::RecordInvalid.new(@my_object) where @my_object is a mock then your exception will not be raised; instead you get a cryptic error. This is because RecordInvalid expects to be able to call certain methods on your ActiveRecord model, which your mock isn’t set up for. So instead, prepare your mock, like so:
@thingy = mock_model Thingy, :field => 'value' prepare_for_errors_on @thingy raise ActiveRecord::RecordInvalid.new(@thingy)
There’s also a short-cut method:
@thingy = invalid_model Thingy, :field => 'value' raise ActiveRecord::RecordInvalid.new(@thingy)
Some helpful matchers for testing HTTP statuses beyond the default be_success (200 OK)
# looks for a 201 Created (useful for API CREATE calls) response.should be_successfully_created # expects a Location field with the given URL (useful for API CREATE calls) response.should point_to(url) # looks for a 422 response (invalid object) response.should be_unprocessable # looks for a 404 response.should be_not_found # looks for a 401 response.should be_unauthorised # looks for a 500 response.should be_an_error
Also a helper for testing which layout was used
# Makes sure it used the "bare" layout response.should use_layout("bare")
One of the issues with writing standard controller specifications, using RSpec’s inbuilt mock objects is that the “flow” of your specs feels wrong.
it "should display a page for a given thingy" do @thingy = mock_model Thingy, :name => 'Wotsit' Thingy.should_receive(:find).with('1').and_return(@thingy) get :show, :id => '1' response.should be_success response.should render_template('thingies/show') end
In other words you are setting expectations before you are doing the work - technically correct but it reads wrongly.
These extra helpers let you write specifications in a more english-like manner.
it "should display a page for a given thingy" do @thingy = mock_model Thingy on_getting :show, :id => '1' do Thingy.should_receive(:find).with('1').and_return(@thingy) end response.should be_success response.should render_template('thingies/show') end
Isn’t that lovely?
Ever wanted to check an array contains the right elements, but not cared about the order they were returned? Enter ComparableArray!
ComparableArray.new([:foo, :bar]).should =~ [:bar, :foo]
And there’s even a shorthand for it
(~[:foo, :bar]).should =~ [:bar, :foo]
It’s not required by default, you need to explicity require it.
require "rspec_rails_extensions/comparable_array"