Flowdock

Notes posted to RSpec

RSS feed
December 1, 2012
0 thanks

This method is deprecated in rspec 2.0

  • be_close(1, 0.1) is deprecated.

  • please use be_within(0.1).of(1) instead.

August 14, 2011
1 thank

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.

April 24, 2011
0 thanks

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
April 22, 2011
0 thanks

Careful when comparing strings

Input String is treated as Regexp:

"*test*".should match "*test*" #=> fail
"*test*".should match ".*test.*" #=> pass

Regexp special characters inside input String can’t [be] escaped:

"*test*".should match "\*test\*" #=> fail
"*test*".should match /\*test*\/ #=> pass
April 22, 2011
0 thanks

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.

April 22, 2011
0 thanks

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
March 31, 2011
0 thanks

Test strings with match

To test a string use match, e.g.

"test".should match("test")
July 21, 2010
1 thank

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.

March 4, 2010 - (>= 1.2.8)
5 thanks

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

June 12, 2009
0 thanks

Reusing shared examples

share_examples_for “a shape” do

   it "should have a color" do
     @shape.color.should == :black
   end
 end

describe "a circle" do
  before(:all) do
    @shape = Circle.new
  end 
  it_should_behave_like "a shape"
end
June 12, 2009
0 thanks

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
June 4, 2009
1 thank

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
June 1, 2009
1 thank

Shared examples

Use it together with share_examples_for like this:

share_examples_for "a shape" do
  it "should have a color" do
    # ...
  end

  it "should have a center point" do
    # ...
  end
end

describe "a circle" do
  it_should_behave_like "a shape"

  it "should be round" do
    # ...
  end
end
June 1, 2009
0 thanks

Typical stub! usage

Typically you would call

my_object.stub!(:updated_at).and_return(time_object)
February 17, 2009
7 thanks

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.

February 4, 2009
0 thanks
February 2, 2009
1 thank

usage

code

@items = Item.find(:all)
@items.should have_at_least(1).item
September 27, 2008
3 thanks

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

August 15, 2008
9 thanks

anything matcher

The anything matcher will match any ruby object:

1.should == anything
nil.should == anything
'string'.should == anything

var.should_receive(:method).with(param1, anything)
August 14, 2008
13 thanks

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')