Specifying raising of errors in RSpec

RSpec allows a developer to specify that an error is raised within a block with the raise_error method. It’s a nice expressive way of saying that your code should fail when it needs to.

But my tiny brain has often been confused with using it at times, more so when the error class requires parameters for instantiation and when used in conjunction with the and_raise method on a stub or a mock

Consider the snippet below where my Widget depends on Thingamajig to do its funky thing in order to run. But Thingamajig is rigged to explode in a mass of funkyness and make Widget all useless.

describe Widget do
it "should re-raise errors as a Widget::UnrecoverableError" do
# expectations
thingamajig = stub(Thingamajig)
thingamajig.should_receive(:do_funky_thing).and_raise(Thingamajig::FunkyExplosion.new('The funky thang exploded yo'))

# our SUT
widget = Widget.new(thingamajig)

lambda { widget.run }.should raise_error(Widget::UnrecoverableError, 'The funky thang exploded yo')

Do you notice the inconsistency between the way errors are declared in the expectation and the actual verification?

# expectations
thingamajig.should_receive(:do_funky_thing).and_raise(Thingamajig::FunkyThingExplosion.new('The funky thang exploded yo'))

lambda { widget.run }.should raise_error(Widget::UnrecoverableError, 'The funky thang exploded yo')

The expectation on the stub, ‘thingmajig’ needs the exception instantiated first while verification requires the class name and parameters used to instantiate the error instance.

And no, doing it like this doesn’t work as expected:

lambda { widget.run }.should raise_error(Widget::UnrecoverableError.new('The funky thang exploded yo'))

It’s an unfortunate impedance mismatch that might be caused due to the way Ruby handles the raising of errors.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s