We all know rspec is sweet. There are a few gotchas, though, that everyone should be aware of. One of them shows up when using the raise_error matcher.

Consider the following bit of code with spec:

class User
  attr_accessor :username
end

class Project
  attr_accessor :users

  def add_user(user)
    raise "User is already on project" if user.users.include? user
  end
end

it 'should not allow you to add multiple users to a project' do
  user = User.new
  project = Project.new

  lambda {
    project.add_user(user)
    project.add_user(user)
  }.should raise_error
end

In this obviously contrived example an error will be raised…but it won’t be the error you expect. You’ll get a NoMethodError! rspec lets you check the type of error raised, so here is a better alternative — notice the differences on linew 1, 11, and 21.

class DuplicateUsersError < StandardError; end

class User
  attr_accessor :username
end

class Project
  attr_accessor :users

  def add_user(user)
    raise DuplicateUsersError, "User is already on project" if user.users.include? user
  end
end

it 'should not allow you to add multiple users to a project' do
  user = User.new
  project = Project.new

  lambda {
    project.add_user(user)
    project.add_user(user)
  }.should raise_error DuplicateUsersError
end

Now the spec will properly fail as the wrong type of error was raised!

Advertisements