How to use RSpec's should_raise with any kind of exception?

88,584

Solution 1

expect { some_method }.to raise_error

RSpec 1 Syntax:

lambda { some_method }.should raise_error

See the documentation (for RSpec 1 syntax) and RSpec 2 documentation for more.

Solution 2

RSpec 2

expect { some_method }.to raise_error
expect { some_method }.to raise_error(SomeError)
expect { some_method }.to raise_error("oops")
expect { some_method }.to raise_error(/oops/)
expect { some_method }.to raise_error(SomeError, "oops")
expect { some_method }.to raise_error(SomeError, /oops/)
expect { some_method }.to raise_error(...){|e| expect(e.data).to eq "oops" }

# Rspec also offers to_not:
expect { some_method }.to_not raise_error
...

Note: raise_error and raise_exception are interchangeable.

RSpec 1

lambda { some_method }.should raise_error
lambda { some_method }.should raise_error(SomeError)
lambda { some_method }.should raise_error(SomeError, "oops")
lambda { some_method }.should raise_error(SomeError, /oops/)
lambda { some_method }.should raise_error(...){|e| e.data.should == "oops" }

# Rspec also offers should_not:
lambda { some_method }.should_not raise_error
...

Note: raise_error is an alias for raise_exception.

Documentation: https://www.relishapp.com/rspec

RSpec 2:

RSpec 1:

Solution 3

Instead of lambda, use expect to:

   expect { some_method }.to raise_error

This is applies for more recent versions of rspec, i.e. rspec 2.0 and up.

See the doco for more.

Solution 4

The syntax changed recently and now it is:

expect { ... }.to raise_error(ErrorClass)

Solution 5

From version 3.3 on rspec-expections gem raises a warning for a blank raise_error without a parameter

expect { raise StandardError }.to raise_error # results in warning
expect { raise StandardError }.to raise_error(StandardError) # fine

This gives you a hint that your code may fail with a different error than the test intended to check.

WARNING: Using the raise_error matcher without providing a specific error or message risks false positives, since raise_error will match when Ruby raises a NoMethodError, NameError or ArgumentError, potentially allowing the expectation to pass without even executing the method you are intending to call. Instead consider providing a specific error class or message. This message can be supressed by setting: RSpec::Expectations.configuration.warn_about_potential_false_positives = false.

Share:
88,584

Related videos on Youtube

marcgg
Author by

marcgg

Trying to build useful software. Find me on twitter or give my blog a read!

Updated on July 25, 2020

Comments

  • marcgg
    marcgg almost 4 years

    I'd like to do something like this:

    some_method.should_raise <any kind of exception, I don't care>
    

    How should I do this?

    some_method.should_raise exception
    

    ... doesn't work.

  • ericraio
    ericraio about 12 years
    I wouldn't use this for Rspec 1 but for Rspec 2 it works just as it should.
  • Guilherme Garnier
    Guilherme Garnier about 12 years
    Actually, according with the documentation link above, this should be expect { some_method }.to raise_error
  • Kragen Javier Sitaker
    Kragen Javier Sitaker about 12 years
    Neither your comment nor the page you link to explains why expect is better or worse than lambda.
  • Rob
    Rob over 11 years
    expect is for rspec 2.0 and higher. This renders moot the argument about which one is better, since the lambda syntax doesn't work any more
  • Sergiy Seletskyy
    Sergiy Seletskyy over 10 years
    raise_error(/oops/) is a great way to check substring in exception message
  • nnyby
    nnyby over 10 years
    This doesn't work for me in capybara: expect { visit welcome_path }.to raise_error
  • Louis Sayers
    Louis Sayers over 10 years
    ahh.. I just noticed the curly braces!
  • Yo Ludke
    Yo Ludke over 8 years
    Thanks for pointing out that raise_error and for raise_exception are interchangeable (y)