70
73

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Railsの認証Gem deviseを使ったテストをする

Last updated at Posted at 2016-03-30

#環境
ruby 2.2.2p95
Rails 4.2.3
devise 3.5.6
minitest 5.8.4
fixture

#deviseの導入
導入方法については詳しい記事がたくさんあるのでそちらを参考にしてください。
Qiita:Deviseの設定手順をまとめてみた。 その1 導入編
とか
Qiita:Rails 4.2 で ユーザー管理・認証 (devise)
とか。

フィールドを追加する場合はこちらを参考にすると良いと思います。
Qiita:Rails + Deviseでusernameを追加する

#testの前に
githubのwikiは目を通しておくと良いでしょう。
あとminitestで書きます。
wikiにはRSpec, factrygirlの書き方が載っていますので参考にしてください。

#functional test
fixtureでユーザーを用意します。

test/fixtures/users.yml
john:
  email: "john@example.com"
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>

コントローラーテストではinclude Devise::TestHelpersを使います。

test/controllers/hoges_controller_test.rb
class hogesControllerTest < ActionController::TestCase
  include Devise::TestHelpers
  def setup
    @user = users( :john )
    sign_in(@user)
  end
end

これだけでuser:johnでログインしたことになり、テストができます。

#integration test
WikiによるとDevise::TestHelpersが使えないようなのでDeviseの核となっているWardenのTestHelperを使います。

test/integration/fuga_test.rb
class FugaTest < ActionDispatch::IntegrationTest
  include Warden::Test::Helpers
  
  def setup
    Warden.test_mode!
    @user = users( :john )
    login_as(@user, :scope => :user)
  end
end

これでコントローラーテストと同様user:johnでログインしたことになります。

#ヘルパーを使う場合
こんな感じでlog_inというメソッドをつくってみると、functional test, integration testどちらでも使えます。
(ログイン周りでもう少し面倒なことをしている場合は、このように共通化しておくと良いと思います。

test/test_helper.rb
class ActiveSupport::TestCase
  def log_in( user )
    if integration_test?
      #use warden helper
      login_as(user, :scope => :user)
    else #controller_test, model_test
      #use devise helper
      sign_in(user)
    end
  end
  
  # 統合テスト内ではtrueを返す
  def integration_test?
    defined?(post_via_redirect)
  end
end

#注意:confirmableについて
メール認証オプションであるconfirmableを利用している場合は普通にログインしてもunauthenticatedが返ってきてしまうため、以下いずれかの対応が必要です。
(自動テストでなければメール配信してリンクをクリックしたり、コンソールに書き出されたURLへアクセスすれば良いのですけどね。)

##1:fixtureで対応する場合
userにconfirmed_atを追記してください。
これでメール認証済みになります。

test/fixtures/users.yml
john:
  email: "john@example.com"
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>
  confirmed_at: <%= Time.now - 100 %>

##2:新規ユーザー作成している場合
テスト中に新規ユーザーを作成するケースがあると思います。
その場合はskip_confirmation!を使うと認証をスキップできます。
(user.confirmでも良いですが、こちらを使うと「本登録完了しました」メールが発送されます。)
※先ほどtest_helper内に作成したlog_inメソッドを利用しています。

test/controllers/hoges_controller_test.rb
user = User.new email: 'john@example.com', password: '12345678'
user.skip_confirmation!
user.save!

log_in( user )

###参考
そんなこと覚えてない: Devise で email 変更する。
Qiita: deviseでconfirmable設定をした際の確認メールをスキップさせる skip_confirmation! は、対象のオブジェクトをsaveする前に書く

#謝辞
Twitterでテストがうまくいかないことを呟いていたら、颯爽と現れてアドバイスをいただいた伊藤淳一さん、本当にありがとうございます。
※ちなみにその時ハマっていたのは最後に書いたconfirmableのところです。

70
73
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
70
73

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?