Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Devise warden error thrown for authenticate_user in functional Rails test

I have a resource where the new action requires a user to be logged in to view. If a user tries to create a new resource without being logged in, they are redirected (302'd) to the login page. My functional test looks like this:

  test "should not get new unless logged in" do
    get :new
    assert_response :redirect
  end

The stacktrace looks something like this:

ArgumentError: uncaught throw :warden
    /.../gems/warden-1.1.1/lib/warden/proxy.rb:114:in `throw'
    /.../gems/ruby-1.9.2-p318/gems/warden-1.1.1/lib/warden/proxy.rb:114:in `authenticate!'
    /.../gems/ruby-1.9.2-p318/gems/devise-2.0.4/lib/devise/controllers/helpers.rb:48:in `authenticate_user!'

I have a before_filter to authenticate_user before the new action.

I understand why authenticate_user! is failing but I can't understand why its throwing an error. Shouldn't it just behave as it does in the webapp ie. redirects user to the log in page?

Thanks.

like image 714
Gerard Avatar asked Jun 22 '12 08:06

Gerard


3 Answers

Do as documentation says:

class ActionController::TestCase
  include Devise::TestHelpers
end

Particularly, don't put include Devise::TestHelpers into classActiveSupport::TestCase.

like image 128
x-yuri Avatar answered Nov 14 '22 10:11

x-yuri


This happens when the Warden and/or Devise inclusions are missing or not added in the proper place. It's tempting to add them into test_helper.rb since that's where helpers typically go but that won't work properly for Devise.

See https://github.com/plataformatec/devise/issues/1029 for more details.

To solve this problem, include both the Devise helper and the Warden helper in controller's test class like this:

require 'test_helper'                                  
class UserControllerTest < ActionController::TestCase  
  include Devise::TestHelpers                          
  include Warden::Test::Helpers                        
  Warden.test_mode!                                    

  def teardown                                         
    Warden.test_reset!                                 
  end                                                  

  # test "the truth" do                               
  #   assert true
  # end
end

This is required for every controller that uses Devise's authentication.

EDIT: As mentioned in the comments below, moving include Warden:TestHelpers from spec_helper.rb (or test_helper.rb) to rails_helper.rb works too.

like image 2
xeorem Avatar answered Nov 14 '22 10:11

xeorem


I got this error, but it was because I put my include Devise::TestHelpers outside of my class definition.

require 'test_helper'
include Devise::TestHelpers

class Admin::ObservationsControllerTest < ActionController::TestCase
  setup do
  ...

This threw the warden error for 3 of my 7 test cases. Moving the include inside the class definition fixed everything.

like image 1
myagi Avatar answered Nov 14 '22 10:11

myagi