ControllerExampleGroup.bypass_rescue

As best I can tell, bypass_rescue from rspec-rails-1 is no longer part
of rspec-rails, ‘> 2’. I had been using it on occasion for things like:

describe CorrespondencesController do

describe ‘#show’ do
it "should raise an AuthorizationError if current user is not the
correspondent " do
bypass_rescue

expect { do_get }.to raise_error(AuthorizationError)

I know there are conflicting opinions on whether or not it’s a good idea
to directly check for exceptions this way, but I’ve always felt that
this was appropriate for testing a controller action in isolation where
the responsibility of the action under test was only to raise the error.

Anyway, I couldn’t find any recent references to this (not even in the
rspec-rails repo). Is there any way to do this in rspec-rails-2 or is
the official consensus to check only on response codes, etc… ?

-lenny

If you are rescuing an exception, test what the rescue does. Purposely
cause the exception, then check the rescue does what it’s supposed to.

Sent from my iPhone

On Aug 11, 2011, at 7:17 AM, Justin Ko wrote:

  expect { do_get }.to raise_error(AuthorizationError)

I know there are conflicting opinions on whether or not it’s a good idea to
directly check for exceptions this way, but I’ve always felt that this was
appropriate for testing a controller action in isolation where the responsibility
of the action under test was only to raise the error.

Anyway, I couldn’t find any recent references to this (not even in the
rspec-rails repo). Is there any way to do this in rspec-rails-2 or is the official
consensus to check only on response codes, etc… ?

-lenny

If you are rescuing an exception, test what the rescue does. Purposely cause the
exception, then check the rescue does what it’s supposed to.

Justin - that specifies how the controller handles exceptions, but not
when they get raised, which is the purpose of bypass_rescue. In Lenny’s
example, above, the GET results in an AuthorizationError, but if that
gets rescued then you have to specify it in terms of what the rescue
does, not how it got to the rescue handler. That’s probably OK in most
cases, but there are cases where you have more than one way to get to a
rescue, and you want to specify the details of how it gets there.

Lenny, this was an oversight. Please submit an issue to
Issues · rspec/rspec-rails · GitHub and we’ll see about getting
this reinstated. No guarantees since so much changed in Rails between v2
and v3, but if it’s reasonable to add I think we should.

Cheers,
David

On Thu, Aug 11, 2011 at 8:40 AM, David C.
[email protected]wrote:


expect { do_get }.to raise_error(AuthorizationError)
official consensus to check only on response codes, etc… ?
they get raised, which is the purpose of bypass_rescue. In Lenny’s example,

“there are cases where you have more than one way to get to a rescue”

Wouldn’t you just mock/do-whatever to ensure the correct path to the
rescue
for the particular example?

On Aug 11, 2011, at 8:59 AM, Justin Ko wrote:


-lenny

If you are rescuing an exception, test what the rescue does. Purposely cause
the exception, then check the rescue does what it’s supposed to.

Justin - that specifies how the controller handles exceptions, but not when they
get raised, which is the purpose of bypass_rescue. In Lenny’s example, above, the
GET results in an AuthorizationError, but if that gets rescued then you have to
specify it in terms of what the rescue does, not how it got to the rescue handler.
That’s probably OK in most cases, but there are cases where you have more than one
way to get to a rescue, and you want to specify the details of how it gets there.

Lenny, this was an oversight. Please submit an issue to
Issues · rspec/rspec-rails · GitHub and we’ll see about getting this
reinstated. No guarantees since so much changed in Rails between v2 and v3, but if
it’s reasonable to add I think we should.

Cheers,
David

This has been taken care of.

:bypass_rescue no longer available in ControllerExampleGroup · Issue #425 · rspec/rspec-rails · GitHub

Thanks David.

-lenny

I agree with Lenny. I can give an example.

Lets say that parts of the application are restricted. Whenever they are
accessed by an unauthorized user, they trigger UnauthorizedAccessError.
Depending on the role the user has in the system, different actions
should
be performed, e.g. unauthenticated users get redirected to the hope
page,
admins see a special message with more details.

The example is a bit synthetic, but I’m sure you can see a similar, real
one.

In the design I have in mind, the logic that handles the
UnauthorizedAccessError is handled in ApplicationController, while the
error
is raised in some specific controller.

If you, in this error-raising path, assert that a non-authenticated user
gets redirected to the homepage, you’re encoding that behavior in the
test.
But this behavior is only accidental to the controller under test. This
makes the test harder to understand. Worse, if you have multiple actions
that raise this exception, you’re encoding the knowledge in multiple
tests.
Now you have duplication too.

I think it makes much more sense to assert that UnauthorizedAccessError
is
raised and specify what happens elsewhere.