Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

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

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

モックを作成する

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

/spec/support/omniauth_macros.rb
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する。

spec/rails_helper.rb
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ログイン/サインアップを制御するコントローラー

app/controllers/sessions_controller.rb
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を書く

spec/features/users_spec.rb
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で連携したユーザーがログインしようとするとユーザーは増えないことをテストする。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした