[rspec-users] specing rescue, ensure and else blocks of an Exception

David Chelimsky dchelimsky at gmail.com
Fri Oct 26 07:56:26 EDT 2007


On 10/26/07, Tarsoly András <tarsolya at gmail.com> wrote:
> Greetings,
>
> I'm using rspec with rcov for my applications and there is one issue which I
> cannot solve nor can find any proper information regarding it: specing what
> is in a rescue block in case of an exception.
>
> I'm using Ruby on Rails and I usually make use of exceptions in my
> controllers, like the following example:
>
> def action
>   @foo = Foo.find(1)
>   @foo.update_attributes!(params[:foo])
>   redirect_to :back
> rescue ActiveRecord::RecordInvalid => e
>   ...exception handling code ...
> rescue Exception => e
>   ...exception handling code ...
> else
>   ...else block
> ensure
>   ...ensure block
> end
>
> I have a specs for this, like this one:
>
> it "should retrieve a Foo instance, identified by ID and update it's
> parameters" do
>   Foo.should_receive(:find).with("1").and_return(@foo)
>
> @foo.should_receive(:update_attributes!).with(valid_params).and_return(@foo)
>   get :action, :id => 1
>   response.should be_redirect
> end
>
> it "should retrieve a Foo instance, identified by ID and throw an exception,
> because of bad parameters" do
>   Foo.should_receive(:find).with("1").and_return(@foo)
>
> @foo.should_receive(:update_attributes!).with(valid_params).and_return(@foo)
>   get :action, :id => 1
>   response.should raise_error
> end
>
> or
>
>
> it "should retrieve a Foo instance, identified by ID and throw an exception,
> because of bad parameters" do
>   Foo.should_receive(:find).with("1").and_return(@foo)
>   lambda {
> @foo.should_receive(:update_attributes!).with(valid_params).and_return(@foo)
> }.should raise_error
>   get :action, :id => 1
> end

There are a few problems with these examples. First of all, they use
"get" when they should use "post", so they're likely not executing the
right stuff.

Next, they are describing expected model behaviour in your controller
spec. What we're interested in here is not that the model raises an
error under certain conditions - that's something we should spec in
model specs - we're interested in what the controller does when the
model raises an error.

Lastly, the examples have AND in them. That should be a red flag. Each
example should describe a single aspect of the behaviour of the action
when invoked under specific circumstances.

Take a look at http://pastie.caboo.se/111125 (reorganized from your
example). Note that each example is about what the controller does,
not what the model does. Also note that there are no "and"s in any of
the labels. Each example sets up one thing and describes what happens
when the action is invoked based on those conditions.

HTH,
David

>
> ... and ... that's it, the tests pass, becaue an Exception is raised, but I
> don't know how to proceed with testing all the rescue, ensure and else
> blocks. Since rcov reporting it as not being run, my coverage is suffering
> and I really don't want to release code which are only being partially
> tested.


More information about the rspec-users mailing list