I was looking for a solution for two things I didn’t know how to solve in RSpec:

  1. How to expect an exception?
  2. How to test a block?

Fortunately I found yesterday answer for my concerns. But before I show you examples, let’s assume we have following class to test.

class ObjectHelper
  def validate(o)
    raise "Object has no 'path' property!" unless o.respond_to?(:path)
  end

  def print_alphabet
    printer do
      ('a'..'z').each do |letter|
        print letter
      end
    end
  end

  def printer(&block)
    instance_eval &block if block
  end

  def print(value)
    puts value
  end
end

And our rspec skeleton:

require 'object_helper'

describe ObjectHelper do
  before(:each) do
    @object_helper = ObjectHelper.new
  end

  # here we place our tests

end

Expecting exceptions

If you want to test for the right exception and message you can use lambda’s, like this:

it "should validate object" do
  o = mock('Object')
  o.should_receive(:respond_to?).with(:path).and_return(true)
  @object_helper.validate(o)
end

it "should raise an exception because there is no 'path' property" do
  o = mock('Object')
  o.should_receive(:respond_to?).with(:path).and_return(false)

  lambda {
    @object_helper.validate(o)
  }.should raise_error("Object has no 'path' property!")
end

Testing a block

Here is the answer for testing a block

it "should print values" do
@object_helper.should_receive(:printer).and_yield do |block|
  block.should_receive(:print).exactly(26).times
end

 @object_helper.print_alphabet
end