I am trying to stub authentication for a controller in rspec. When I stub the authorize
method the test always passed no matter what the value I supply.
Controller:
class FoosController < ApplicationController
before_filter :authorize
...
end
ApplicationController:
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_user
protected
def authorize
return true if current_user
fl开发者_运维知识库ash[:error] = 'Please login'
redirect_to signin_path
false
end
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
Specs:
# this passes (expected)
it "..." do
controller.stubs(:current_user).returns(User.new)
get :index
response.should be_success
end
# this fails (expected)
it "..." do
controller.stubs(:current_user).returns(nil)
get :index
response.should be_success
end
# this passes (expected)
it "..." do
controller.stubs(:authorize).returns(true)
get :index
response.should be_success
end
# Problem: this passes (unexpected)
it "..." do
controller.stubs(:authorize).returns(false)
get :index
response.should be_success
end
It seems like as soon as I stub :authorize, no matter what value is set, it always passes the before_filter. I thought it might be the protected/helper_method designations, but playing with those didn't change anything.
Why does stubbing :authorize with false cause the before_filter to pass?
I think you need to check WHAT is being rendered.
Looking at your code, if the call-chain does indeed stop when authorize
returns false,
then what is going to happen?
There is no redirect, or render call.
So it will be an empty response?
An empty response would still be a 200.
However, depending what version of Rails you're using, its possible in Rails 3.1 that a before_filter
returning false
no longer stops the chain.
Really, a before_filter
that wants to stop the chain should do one of the following
- redirect somewhere
- render something
- raise something
I'll answer your last question Why does stubbing :authorize with false cause the before_filter to pass?
You're stubbing the method authorize, which literally stops all the code inside of it to be called but returns what you are explicitly returning with the stub.
It is working properly, because when you stub current_user
to false
then the authorize is called completely. I think your lasts tests are not actually testing anything for you but thats just my opinion.
精彩评论