0
0

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 3 years have passed since last update.

Railsチュートリアル 第12章 パスワードの再設定 - PasswordResetsコントローラーのeditアクションに対するテストは、どのような実装抜けがあったらテストが失敗するのか

Last updated at Posted at 2019-12-15

前提

Railsチュートリアル 第12章のうち、PasswordResetsコントローラーのeditアクションの動作を、テスト駆動で実装していったところです。以下のようなテストが、失敗なしで一気に成功してしまいました。このままでは、どのテストが何に対してのものなのかがわからないですね。

# メールアドレスが無効
get edit_password_reset_path(user.reset_token, email: "")
assert_redirected_to root_url
# 無効なユーザー
user.toggle!(:activated)
get edit_password_reset_path(user.reset_token, email: user.email)
assert_redirected_to root_url
user.toggle!(:activated)
# メールアドレスが有効で、トークンが無効
get edit_password_reset_path('wrong token', email: user.email)
assert_redirected_to root_url
# メールアドレスもトークンも有効
get edit_password_reset_path(user.reset_token, email: user.email)
assert_template 'password_resets/edit'
assert_select "input[name=email][type=hidden][value=?]", user.email

どのような実装抜けがあったら、どのテストが失敗するのでしょうか。

無効なメールアドレスがチェックされない場合

PasswordResetsコントローラーのvalid_userの実装が以下のようになっていたらどうなるでしょうか。

class PasswordResetsController < ApplicationController
  before_action :get_user, only:   [:edit, :update]
  before_action :valid_user, only: [:edit, :update]

  # ...略

  private

    def get_user
      @user = User.find_by(email: params[:email])
    end

    # 正しいユーザーかどうか確認する
    def valid_user
      unless (@user.activated? &&
              @user.authenticated?(:reset, params[:id]))
        redirect_to root_url
      end
    end
end
# rails test test/integration/password_resets_test.rb
Running via Spring preloader in process 762
Started with run options --seed 53179

ERROR["test_password_resets", PasswordResetsTest, 4.072652899998502]
 test_password_resets#PasswordResetsTest (4.07s)
NoMethodError:         NoMethodError: undefined method `activated?' for nil:NilClass
            app/controllers/password_resets_controller.rb:32:in `valid_user'
            test/integration/password_resets_test.rb:28:in `block in <class:PasswordResetsTest>'

  1/1: [===================================] 100% Time: 00:00:04, Time: 00:00:04

Finished in 4.07946s
1 tests, 8 assertions, 0 failures, 1 errors, 0 skips

私の環境では、test/integration/password_resets_test.rbの28行目は以下のコードが記述されています。

get edit_password_reset_path(user.reset_token, email: "")

email属性として空文字列を与えた場合に、「activated?メソッドが定義されていない」というエラーが発生している、ということのようです。

email属性として空文字列を与えた場合、@userの状態はどうなるか

activated?メソッドが定義されていない」というエラーが発生する直前にdebuggerを入れると、結果はどうなるでしょうか。

  class PasswordResetsController < ApplicationController
    before_action :get_user, only:   [:edit, :update]
    before_action :valid_user, only: [:edit, :update]

    ...略

    private

      def get_user
        @user = User.find_by(email: params[:email])
      end

      # 正しいユーザーかどうか確認する
      def valid_user
+       debugger
        unless (@user.activated? &&
                @user.authenticated?(:reset, params[:id]))
          redirect_to root_url
        end
      end
  end
(byebug) @user
nil

「無効なメールアドレスをクエリパラメータとしてUser.find_byメソッドが呼び出されたため、@usernilになってしまっている」ということのようです。

有効化されていないユーザーがチェックされない場合

PasswordResetsコントローラーのvalid_userの実装が以下のようになっていたらどうなるでしょうか。

class PasswordResetsController < ApplicationController
  before_action :get_user, only:   [:edit, :update]
  before_action :valid_user, only: [:edit, :update]

  # ...略

  private

    def get_user
      @user = User.find_by(email: params[:email])
    end

    # 正しいユーザーかどうか確認する
    def valid_user
      unless (@user &&
              @user.authenticated?(:reset, params[:id]))
        redirect_to root_url
      end
    end
end

test/integration/password_resets_test.rbに対するテストの結果は以下のようになります。

# rails test test/integration/password_resets_test.rb
Running via Spring preloader in process 788
Started with run options --seed 20070

 FAIL["test_password_resets", PasswordResetsTest, 3.081338899995899]
 test_password_resets#PasswordResetsTest (3.08s)
        Expected response to be a <3XX: redirect>, but was a <200: OK>
        test/integration/password_resets_test.rb:33:in `block in <class:PasswordResetsTest>'

  1/1: [===================================] 100% Time: 00:00:03, Time: 00:00:03

Finished in 3.10585s
1 tests, 10 assertions, 1 failures, 0 errors, 0 skips

私の環境では、test/integration/password_resets_test.rbの30行目から33行目には以下のコードが記述されています。

# 無効なユーザー
user.toggle!(:activated)
get edit_password_reset_path(user.reset_token, email: user.email)
assert_redirected_to root_url

メッセージの内容は以下です。

Expected response to be a <3XX: redirect>, but was a <200: OK>

ということは、「ユーザーが有効化されていない場合に、リダイレクトされるべきところがリダイレクトされていない」という理由でのテストの失敗のようですね。

パスワード再設定用トークンの有効性がチェックされない場合

PasswordResetsコントローラーのvalid_userの実装が以下のようになっていたらどうなるでしょうか。

class PasswordResetsController < ApplicationController
  before_action :get_user, only:   [:edit, :update]
  before_action :valid_user, only: [:edit, :update]

  # ...略

  private

    def get_user
      @user = User.find_by(email: params[:email])
    end

    # 正しいユーザーかどうか確認する
    def valid_user
      unless (@user && @user.activated?)
        redirect_to root_url
      end
    end
end

test/integration/password_resets_test.rbに対するテストの結果は以下のようになります。

# rails test test/integration/password_resets_test.rb
Running via Spring preloader in process 801
Started with run options --seed 55315

 FAIL["test_password_resets", PasswordResetsTest, 3.1079486000016914]
 test_password_resets#PasswordResetsTest (3.11s)
        Expected response to be a <3XX: redirect>, but was a <200: OK>
        test/integration/password_resets_test.rb:37:in `block in <class:PasswordResetsTest>'

  1/1: [===================================] 100% Time: 00:00:03, Time: 00:00:03

Finished in 3.11229s
1 tests, 11 assertions, 1 failures, 0 errors, 0 skips

私の環境では、test/integration/password_resets_test.rbの35行目から37行目には以下のコードが記述されています。

# メールアドレスが有効で、トークンが無効
get edit_password_reset_path('wrong token', email: user.email)
assert_redirected_to root_url

メッセージの内容は以下です。

Expected response to be a <3XX: redirect>, but was a <200: OK>

ということは、「パスワード再設定用トークンが有効でない場合に、リダイレクトされるべきところがリダイレクトされていない」という理由でのテストの失敗のようですね。

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?