9

I'm searching for a solution for a weird problem. I have a controller, that needs authentication (with the devise gem). I added the Devise TestHelpers but i can't get it working.

require 'test_helper'

class KeysControllerTest < ActionController::TestCase  
   include Devise::TestHelpers  
   fixtures :keys

   def setup
      @user = User.create!(
        :email => 'testuser@demomailtest.com',
        :password => 'MyTestingPassword',
        :password_confirmation => 'MyTestingPassword'
      )
      sign_in @user
      @key = keys(:one)
   end

   test "should get index" do
      get :index    
      assert_response :success
      assert_not_nil assigns(:keys)
   end

   test "should get new" do
      get :new
      assert_response :success
   end

   test "should create key" do
      assert_difference('Key.count') do
         post :create, :key => @key.attributes
      end

      assert_redirected_to key_path(assigns(:key))
   end

   test "should destroy key" do
      assert_difference('Key.count', -1) do
         delete :destroy, :id => @key.to_param
      end

      assert_redirected_to keys_path
   end

end

And i get the following output in my "rake test" window:

29) Failure:
test_should_create_key(KeysControllerTest) [/test/functional/keys_controller_test.rb:29]:
"Key.count" didn't change by 1.
<3> expected but was
<2>.

 30) Failure:
test_should_destroy_key(KeysControllerTest) [/test/functional/keys_controller_test.rb:37]:
"Key.count" didn't change by -1.
<1> expected but was
<2>.

 31) Failure:
test_should_get_index(KeysControllerTest) [/test/functional/keys_controller_test.rb:19]:
Expected response to be a <:success>, but was <302>

 32) Failure:
test_should_get_new(KeysControllerTest) [/test/functional/keys_controller_test.rb:25]:
Expected response to be a <:success>, but was <302>

Can someone tell my, why devise doesn't authenticate? I'm using the exact same procedure for an AdminController and it works perfect.

axx
  • 133
  • 1
  • 4

3 Answers3

24

Are you using Devise with confirmable? In this case, create is not enough and you need to confirm the user with @user.confirm!

Second, why do you create the user in the functional test? Declare your users in the fixture like this (confirmed_at if you require confirmation only):

test/fixtures/users.yml:

user1: 
id: 1
email: user1@test.eu
encrypted_password: abcdef1
password_salt:  efvfvffdv
confirmed_at: <%= Time.now %>

and sign them in in your functional tests with:

sign_in users(:user1)

Edit: I just saw, that in my app the Devise-Testhelpers are declared in test/test-helpers.rb and I don't know if this makes a difference, maybe you want to try:

ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'

class ActionController::TestCase
  include Devise::TestHelpers
end

class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
  #
  # Note: You'll currently still have to declare fixtures explicitly in integration tests
  # -- they do not yet inherit this setting
  fixtures :all

  # Add more helper methods to be used by all tests here...
end
Markus Proske
  • 3,356
  • 3
  • 24
  • 32
  • Awesome! Yes, i am using the confirmable setting. Since changing it like you described it, it works like a charm. :) – axx Apr 10 '11 at 16:35
  • 1
    Does this really work? I mean, devise encrypts passwords before putting it into the database, and as far as I know fixtures are directly written into the database. This means that the decrypting should fail (because abcdef1 won't decrypt properly). – Justus Romijn Oct 27 '11 at 11:34
  • Can anyone add a pointer to the correct answer for newer versions of Devise? – Peter Andersson Sep 30 '13 at 12:48
  • Yes, encrypted_password needs to be set with inline code to actually update the column with encrypted data. See http://stackoverflow.com/a/10427785/18706 – mahemoff Jan 23 '14 at 17:48
1

This took me some time to figure out but it turns out the answer is really simple.

The point is that, in your fixtures file (users.yml), you need to make sure the user is 'confirmed' (assuming that you specified "confirmable" in your User model). So, for instance, put this in your users.yml:

user_one:
  confirmed_at: 2015/01/01

That's all, no need to specify other fields (email, encrypted password, etc).

Now in your controller test (e.g. in 'setup' or in 'before') you simply code:

sign_in users(:user_one)

And then it should just work!

leo
  • 1,175
  • 12
  • 13
0

I had a similar issue (but using FactoryGirl, rather than Fixtures) and was able to resolve it by simply using FactoryGirl.create(:user) rather than FactoryGirl.build(:user).

Evidently, Devise requires the user to have been persisted to the Database, for everything to work properly.

XtraSimplicity
  • 5,704
  • 1
  • 28
  • 28