58

I am wanting to test a function on one of my models that throws specific errors. The function looks something like this:

def merge(release_to_delete)
  raise "Can't merge a release with itself!" if( self.id == release_to_delete.id )
  raise "Can only merge releases by the same artist" if( self.artist != release_to_delete.artist   )
  #actual merge code here
end

Now I want to do an assert that when I call this function with a parameter that causes each of those exceptions, that the exceptions actually get thrown. I was looking at ActiveSupport documentation, but I wasn't finding anything promising. Any ideas?

spilliton
  • 3,811
  • 5
  • 35
  • 35

2 Answers2

124

So unit testing isn't really in activesupport. Ruby comes with a typical xunit framework in the standard libs (Test::Unit in ruby 1.8.x, MiniTest in ruby 1.9), and the stuff in activesupport just adds some stuff to it.

If you are using Test::Unit/MiniTest

assert_raise(Exception) { whatever.merge }

if you are using rspec (unfortunately poorly documented, but way more popular)

lambda { whatever.merge }.should raise_error

If you want to check the raised Exception:

exception = assert_raises(Exception) { whatever.merge }
assert_equal( "message", exception.message )
Jon Schneider
  • 25,758
  • 23
  • 142
  • 170
Matt Briggs
  • 41,224
  • 16
  • 95
  • 126
  • 8
    Thanks! I had to use "RuntimeError" instead of exception though, like this: assert_raise( RuntimeError ){ artist1.merge(artist1) } This guide was extremely helpful: http://guides.rubyonrails.org/testing.html – spilliton Aug 18 '10 at 00:58
  • 1
    @spilliton: Thats because the Ruby interpreter treats the code above as `assert_raise(Exception() { whatever.merge })`, i.e. it looks for a method called `Exception` which is called with the given block. Adding the parentheses resolves that ambiguity. (Already fixed the answer) – Daniel Rikowski Oct 20 '12 at 15:08
  • In rspec 3, use `expect { whatever.merge }.to raise_error` (http://www.relishapp.com/rspec/rspec-expectations/v/3-1/docs/built-in-matchers/raise-error-matcher) – Jared Beck Nov 19 '14 at 16:00
17

To ensure that no exception is raised (or is successfully handled) do inside your test case:

assert_nothing_raised RuntimeError do
  whatever.merge
end

To check that error is raised do inside your test case:

assert_raise RuntimeError do
  whatever.merge
end

Just a heads up, whatever.merge is the code that raises the error (or doesn't, depending on the assertion type).

shivam
  • 16,048
  • 3
  • 56
  • 71