Devise warden error thrown for authenticate_user in functional Rails test
Asked Answered
M

4

7

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.

Monotint answered 22/6, 2012 at 8:26 Comment(3)
Did you ever find a way to test a case where the user is not logged in? I'm having a similar issue.Appendicle
I'm not sure how I eventually got this working but it may be down to adding 'include Devise::TestHelpers' to the test class. Feel free to add a pastebin with your code and I'll try to have a look.Monotint
in my case this turned out to be a js: true in the feature declaration (which I did not need, and was somehow causing this error)Simdars
O
5

Do as documentation says:

class ActionController::TestCase
  include Devise::TestHelpers
end

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

Openmouthed answered 23/4, 2015 at 22:34 Comment(0)
P
2

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.

Pipsqueak answered 22/12, 2013 at 2:5 Comment(4)
You don't need to include the helpers in every class. You can just add the following to your test_helper:class ActionController::TestCase include Devise::TestHelpers include Warden::Test::Helpers end (sorry about the lack of proper whitespace)Inventive
Your "answer" does not work at all. Sorry, but that's really not an appropriate answer, to include all the clutter in your controller.Wedding
I had this problem for this reason, and moving config.include Devise::TestHelpers from spec_helper.rb to rails_helper.rb solved it (by including the module later in the chain).Wesle
@Wesle : you are totally right, thank you so much for your help!Tother
B
1

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.

Biflagellate answered 27/7, 2016 at 15:46 Comment(0)
C
0

I know this is an old question now but I found the answer of the Devise wiki

https://github.com/plataformatec/devise/wiki/How-To%3a-Test-with-Capybara

This has a step by step guide that is too involde to re-create here, however the first step is to include the Warden test helpers

include Warden::Test::Helpers
Warden.test_mode!

Hope this helps

Coarsen answered 23/7, 2013 at 17:42 Comment(2)
This happened to me when I had extra logic tied into a user (they needed to be approved by an admin, which didn't come up on my Devise problems radar). So, even if a user is valid, make sure they have all the correct flags / permissions to be able to see the page.Nitrate
See my answer above. You'll also want to include Warden.test_reset! in your teardown function to undo any changes at the end of your tests. Otherwise, any warden actions performed in one test case (e.g. logging in) will spill over into the next.Pipsqueak

© 2022 - 2024 — McMap. All rights reserved.