LoginSignup
70
73

More than 3 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