Good notes posted to RSpec
RSS feed![Default_avatar_30](https://www.gravatar.com/avatar/27327ca97512c92e140ad7e5d6d8a212?size=30&default=http://apidock.com/images/default_avatar_30.png)
![Default_avatar_30](https://www.gravatar.com/avatar/8cb2fab8fddc8626073f40f0106c0077?size=30&default=http://apidock.com/images/default_avatar_30.png)
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
![Default_avatar_30](https://www.gravatar.com/avatar/40e75e91ba81120383c7223690e9bcc0?size=30&default=http://apidock.com/images/default_avatar_30.png)
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.
![Default_avatar_30](https://www.gravatar.com/avatar/73174d2a6d799c23d0200b2afaed0ee1?size=30&default=http://apidock.com/images/default_avatar_30.png)
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
![Default_avatar_30](https://www.gravatar.com/avatar/7a7a5a9574e745f49a65aaa6a93df3c8?size=30&default=http://apidock.com/images/default_avatar_30.png)
![Default_avatar_30](https://www.gravatar.com/avatar/7a7a5a9574e745f49a65aaa6a93df3c8?size=30&default=http://apidock.com/images/default_avatar_30.png)
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')