request.env['warden'] is nil in Rails controller test
manubo opened this issue · 11 comments
In my controller tests in Rails 4.2.2 (MiniTest), request.env['warden'] is always nil in the tested controller. I include Warden::Test::Helpers into ActiveSupport::TestCase.
# test_helper.rb
class ActiveSupport::TestCase
include Warden::Test::Helpers
end
I also have Capybara tests, where the issue does not occur. What am I missing?
# controllers/concern/authenticatable.rb
module Authenticatable
extend ActiveSupport::Concern
def self.included(base)
base.helper_method :warden, :current_user, :signed_in?
end
def logout(scope = default_scope)
warden.logout(scope)
end
def signed_in?(scope = default_scope)
!current_user(scope).nil?
end
def current_user(scope = default_scope)
warden.user(scope)
end
def warden
request.env['warden'] # <-- is nil in MiniTest controller tests
end
def authenticate!(scope = default_scope)
warden.authenticate!(scope: scope)
end
private
def default_scope
warden.config.default_scope
end
end
# controllers/application_controller.rb
class ApplicationController < ActionController::Base
include Authenticatable
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
# test/controllers/accounts_controller_test.rb
require 'test_helper'
class AccountsControllerTest < ActionController::TestCase
setup do
@account = accounts(:cash)
login_as users(:john)
end
teardown do
Warden.test_reset!
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:accounts)
end
end
I realized the middleware stack is not processed by rails in controller tests. Thus, this is not a Warden issue, please ignore my post. I went with this solution.
@manubo can you test this branch: https://github.com/acaron/warden/tree/fix-test-helpers
Add Warden::Test::Mock
and you can call warden
to get a valid warden object (remove your current solution to test this). I needed the exact same thing! Tell me if your tests pass because env
and app
are simulate. The current version 1.2.5
implement this in Warden::Test::Helpers
if that is easier for you to test on. It must be changed because it breaks tests for many people who don't need this!
Version 1.2.6 should solve your problem if you add Warden::Test::Mock
and call warden
.
@acaron I just hit this exact issue. In this solution, do we need to monkey patch Authenticatable#warden to return Warden::Test::Mock#warden instead of request.env['warden']?
Also, I just noticed that this fails if you don't have a :password strategy defined. the proxy raises "Invalid strategy password". I got around it for now by adding a duplicate strategy with a different name, but I don't have immediate suggestions offhand for how to fix that.
@orenmazor you only have to include Warden::Test::Mock
and use directly warden
instead of request.env['warden']
. No monkey patch needed anymore. I don't have have strategy password defined in my tests and it works. Do you have a code sample?
I did, but unfortunately I refactored it out. I'll spin up a sample app for you this weekend.
This worked for me:
@request.env['warden'] = @warden
Controller test helpers for Warden _Kentaro Imai.pdf
Here is a PDF of the article linked in #117 (comment). I had to find it on the wayback machine, so leaving it here in case it disappears.
Controller test helpers for Warden _Kentaro Imai.pdf
Here is a PDF of the article linked in #117 (comment). I had to find it on the wayback machine, so leaving it here in case it disappears.
Nice idea! thanks! here is the same pdf but cleaner (I removed unrelated divs and texts which were covering part of the code):
Controller test helpers for Warden _Kentaro Imai.pdf