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
flash[: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
authorizereturns 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_filterreturningfalseno longer stops the chain.Really, a
before_filterthat wants to stop the chain should do one of the following