kikeda1104's blog

備忘録・技術に関することを書いています。(webエンジニア)

認証機能のユニットテスト(controller)

今日は、自作のアプリでユニットテストを作っていたので、このあたりを書いていきたいと思います。

自作アプリでは認証のgemは使っていないんですが、記事のためにsorceryを使って書いていきます。

  • gemの導入手順は省いています。

準備

# Gemfile
gem 'sorcery'

group :development, :test do
  ...
  gem 'rspec-rails'
  gem 'factory_girl_rails'
end

group :test do
  gem 'capybara'
  gem 'database-clearer'
  gem 'rails-controller-testing' # render_templateを利用するため
end

controller

# admin/sessions_controller.rb

class Admin::SessionsController < Admin::BaseController
  def new
  end

  def create
     user = login(
                  user_params[:email],
                  user_params[:password],
                  user_params[:password_confirmation]
                 )
     if user
       redirect_to dashboard_path, notice: 'ログインに成功しました'
     else
       redirect_to root_path, alert: '認証に失敗しました'
     end
  end

  ...

  def user_params
    params.require(:user).permit(User.column_names)
  end
  private :user_params
end
# admin/dashboard_controller.rb

class DashBoardController < Admin::BaseController
  before_action :require_login
  
  def index
  end
end

models

 # app/models/user.rb
class User < ApplicationRecord
end

spec

# spec/rails_helper.rb

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } # コメントアウトから戻す

Rspec.configure do |config|
  ...
  # sorceryのwikiより
  config.include Sorcery::TestHelpers::Rails::Controller, type: :controller
  config.include Sorcery::TestHelpers::Rails::Integration, type: :feature

  config.include Capybara::DSL
  # FactoryGirlの記載を省くために、追加
  config.include FactoryGirl::Syntax::Methods
  ...
end

spec/factories/user.rb

FactoryGirl.define do
  factory :user do
    email 'gankai1104@gmail.com`
    password 'secret'
    password_confirmation 'secret'
    ...
  end
end

spec/controllers/admin/sessions_controller_spec.rb

require 'rails_helper'
Rspec.describe Admin::SesssionsController, type: :controller do
  describe 'GET #new' do
    it 'ログイン画面へのアクセス時' do
     get :new
     expect(:response).to render_template :new
    end
  end

  describe 'POST #create' do
    it 'ログイン成功時' do
      create(:user)
      post :create, { user: attributes_for(:user) } }
      expect(response).to redirect_to dashboard_path
    end
  
    it 'ログイン失敗時' do
      post :create,  { user: attributes_for(:user) } }
      expect(:response).to render_template :new
    end
  end

  ...
end

spec/controllers/admin/dashboard_controller.rb

RSpec.describe Admin::DashboardController, type: :controller do
  describe 'GET #index' do
    it 'ログイン後の時' do
      login_user(create(:user))
      get :index
      expect(response).to render_template :new
    end

    it 'ログイン前の時' do
      get :index
      expect(response).to redirect_to login_path    
    end
  end
end

ここまでです。 FactoryGirlのtrait, association, Rspecanonymous controllerを利用したので、次はそれを書きます。

参考

Testing Rails · NoamB/sorcery Wiki · GitHub

Cucumber + CapybaraでUserAgentを設定してテストを行う - tech-kazuhisa's blog