🤖

🤖

:gijutsu_burogu:

🍺RSpecでOmniAuthのFacebookログイン/サインアップのFeatureテストを書く

この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。

はじめに

テストを書くのが嫌い/苦手な人はたくさんいると思う。 ものづくりが好きな人にとってテストはなにも生み出されている気がしなくて退屈だ。 そして、テストでエラーが出てもテストのどこが間違えているのかよくわからない。 なぜ、このテストが通らんのやァって発狂しそうになる。 全部、自分のことだ。

最近はRSpecによるRailsテスト入門という本を参考に自分のRailsアプリにRSpecを書きながら苦手克服を目指している。 この本はとてもわかりやすくまとめられていると思う。 Facebookログイン部分のテストはRSpecによるRailsテスト入門にもあまり詳しく書いていなかったのでここでまとめてみる。

モックを作成する

helperとしてメソッドを定義する。

module OmniauthMacros
  def facebook_mock
    OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new(
      {
        provider: 'facebook',
        uid: '12345',
        info: {
          name: 'mockuser',
          email: 'sample@test.com'
        },
        credentials: {
          token: 'hogefuga'
        }
      }
    )
  end
end

設定する

OmniAuth.config.test_mode = trueはOmniAuthが呼ばれたら実際の通信を行わずにテストモードに入ることを意味する。 config.include OmniauthMacrosは先ほどのhelperをrequireする。

require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!

  # -----------以下を追加-----------
  OmniAuth.config.test_mode = true
  config.include OmniauthMacros

end

Facebookログイン/サインアップを制御するコントローラー

class SessionsController < ApplicationController

  def callback
    auth = request.env["omniauth.auth"]
    user = User.find_by(provider: auth["provider"], uid: auth["uid"]) || User.create_with_facebook(auth)
    session[:user_id] = user.id
    redirect_back_or root_path
  end

end

別にOmniAuthでデータをとってくるコードならなんでも良い。

Specを書く

require "rails_helper"

describe "UserFeature" do

  describe "facebook連携でサインアップする" do

    before do
      OmniAuth.config.mock_auth[:facebook] = nil
      Rails.application.env_config['omniauth.auth'] = facebook_mock
      visit root_path
      click_link "ログイン"
    end

    it "サインアップするとユーザーが増える" do
      expect{
        click_link "Facebookでログイン"
      }.to change(User, :count).by(1)
    end

    it "すでに連携されたユーザーがサインアップしようとするとユーザーは増えない" do
      click_link "Facebookでログイン"
      click_link "ログアウト"
      click_link "ログイン"
      expect{
        click_link "Facebookでログイン"
      }.not_to change(User, :count)
    end

  end
end

before節

  • env['omniauth.auth']に先ほどのモックをセットし、ログイン画面へのリンクをクリックする。

it節

  • 実際にログインを行うボタンをクリックするとユーザーが新しく作成されることをテストする。
  • すでに、Facebookで連携したユーザーがログインしようとするとユーザーは増えないことをテストする。