Good notes posted to RSpec
RSS feed

stub_chain is very useful when testing controller code
or any other chained method call type that you’d like to stub, example:
in your controller:
def new @user = current_site.users.new end
in your spec:
it "#new should assign a @user" do u = mock("User") controller.stub_chain(:current_site, :users, :new).and_return(u) assigns[:user].should == u end
whereas before you had to stub each chained method call separately:
it "#new should assign a @user" do u = mock("User") users = mock("Users collection", :new => u) site = mock("Site", :users => users) controller.stub!(:current_site).and_return(site) assigns[:user].should == u end
Please note that stub_chain was added to RSpec in version 1.2.6

Usage examples
Basic usage:
User.should_receive(:find).with(:all, anything).and_return("hello world")
Now:
User.find(:all, :conditions => "foo") #=> "hello world"
But you can also use blocks for more complex matching logic. For example:
User.should_receive(:find) { |*args| if args.size == 2 "received two arguments" else "something else" end }.at_least(:once)
Now:
User.find(:all, :conditions => "bar") #=> "received two arguments" User.find(5) #=> "something else"
Of course normally you’d return mocks instead of strings.

Example using simple_matcher
This is extracted from: http://blog.davidchelimsky.net/2008/6/7/thoughts-on-the-dance-off
Here’s an example:
def be_sorted simple_matcher("a sorted list") {|actual| actual.sort == actual} end [1,2,3].should be_sorted
The block is handed the actual value. If the block returns true, the expectation passes. If it returns false, it fails with the following message:
expected “a sorted list” but got [1, 3, 2]
If you say [1,2,3].should_not be_sorted you’d get this message instead=:
expected not to get “a sorted list”, but got [1, 2, 3]
As of now, you don’t get any control over the failure message other than the string you pass to the simple_matcher method


Testing an options hash receives certain parameters
This method is very useful for testing methods that use the ruby idiom of accepting a hash with configurable options.
class Example def self.find(options = {}) ... end end
We can use hash_including to ensure that certain options are passed in when mocking it.
Example.should_receive(:find).with(hash_including(:conditions => 'some conditions')) Example.find(:conditions => 'some_conditions', :order => 1) # => Passes expectation Example.find(:order => 1) # => Fails expectation
This can also be used to great effect with the anything matcher. For example:
hash_including(:key => anything) hash_including(anything => 'value')