Notes posted to RSpec
RSS feedHelp Link :)
www.relishapp.com/rspec/rspec-mocks/docs/message-expectations/receive-counts!
This method is deprecated in rspec 2.0
-
be_close(1, 0.1) is deprecated.
-
please use be_within(0.1).of(1) instead.
stub/stub! will always be followed by '.and_return'
this function will aways be followed by ‘.and_return(…)’ because a stub is typically used for returning values. The required argument given to stub is a method name. When a message to this stubbed method name is received by a class or existing object of the class AND ‘.and_return’ is provided, the stub will return whatever was provided as argument to ‘.and_return’.
For example,
HomeLoan.stub!(interest_rate).and_return(‘5.5%’)
-
this will return 5.5% when a message for interest_rate in a HomeLoan class’s object is received.
HomeLoan.stub!(interest_rate).and_return(‘5.5%’, ‘3%’)
-
this will return 5.5% when a message for interest_rate in a HomeLoan class’s object is received FOR THE FIRST TIME but will return 3% for subsequent calls/messages.
Input strings are treated as regexp
Input strings are treated as regexp, but you can escape special regexp characters as usual:
"*test*".should match "\\*test\\*" #=> pass "*test*".should match '\*test\*' #=> pass "*test*".should match /\*test\*/ #=> pass
Eql equals ==
Use eql to compare values as you would use ==:
"test".should eql "test" #=> pass "test".should == "test" #=> pass
Do not confuse with equal which compares objects.
Test strings with eql
Equal fails when comparing two different string objects:
"test".should equal "test" #=> fail "test".should match "test" #=> pass "test".should eql "test" #=> pass
In fact:
"test".object_id.should_not eql "test".object_id #=> pass
Match fails when the string contains regex special characters not escaped:
"*test*".should match "*test*" #=> fail for invalid regex "*test*".should eql "*test*" #=> pass
In fact, match treats input as regexp:
"*test*".should match /\*test\*/ #=> pass
Works only inside the "it" block
Please note that stub_chain doesn’t work outside of the it...do...end block.
If you need to create more complicated chains using a function you need to use the old way.
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
A stub with argument and return value
it “should use a dummy method with argument and return value” do
dummy = mock("dummy").stub!(:emulate) dummy.should_receive(:emulate).with(:something).and_return("Done! sir!") dummy.emulate(:something).should == "Done! sir!" end
A typical usage for a mock
You want to use a mock when you’re testing a behaviour of one of your methods that interacts with some outside world service (eg. an FTP server).
it "should login to ftp server" do ftp = mock('Ftp server', :null_object => true) Net::FTP.should_receive(:new).and_return(ftp) ftp.should_receive(:login).with('username', 'password') some_obj.connect end def connect session = Net::FTP.new('server.com') session.login('username', 'password') session.close end
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.
Examples
see have_at_least or have
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')


