1
/
5

Mockを使って、Facebookログイン部分のRSpecを書いてみた!!

こんにちは、エンジニアの神山です。

最近、テストカバレッジを上げるためRSpecを書きまくっています。ちなみに最初は90%でしたが、苦闘の末95%まで上がりました。結構骨が折れましたね。

その中でも大変だったのがFacebookログイン部分のテストです。外部APIを使っており、そこの部分のテストの書き方が分からなくて悩んでいました。

色々と調べてみるとモックを使うとうまいことテスト出来るよという文献を見つけました。


ということで今回は、外部API部分のテストの問題点、モックとは何か、またそれをどのようにテストに使うのかにフォーカスして記事を書きました。

外部API部分のテストの問題点

今回悩んだのは外部APIを使用している部分のテストをどのように書くかということです。


例えば、「ログインしようとしているユーザーのFacebookのアカウント情報を取得し、すでにDBに登録されていればログインさせる」ということです。

しかしこのテストを行うには、実際にFacebookAPIよりアカウント情報を取得しなくてはいけません。


しかしテストで外部APIを利用することには、幾つかのデメリットがあります。

  • 外部APIやその周辺で、予測や対応ができないエラーが起きることがある
  • 外部APIの使用に制限があったり、金銭などが発生する場合がある
  • 外部APIに紐付いているプロダクトにリアルに影響が起こる(Facebookの場合、実際に投稿がされてしまうなど)


では、どうすれば外部APIを利用せずに、外部API部分を使用している部分のテストを出来るのでしょうか。

そのようなときに使うのが、「モック」です。


モックとは何か。

モックを直感的に説明すると、「本物のふりをするニセモノのプログラム」です。下記の記事の言葉を使わせて頂きました。


使えるRSpec入門・その3「ゼロからわかるモック(mock)を使ったテストの書き方」 - Qiita
この記事は最終更新日から1年以上が経過しています。 みなさんこんにちは! この記事は「必要最小限の努力で最大限実戦で使える知識を提供するRSpec入門記事」、略して「使えるRSpec入門」の第3回です。 今回はRSpecのモックを使ったテストについて説明します。 これまでモックを全く使ったことがない人でもわかるように丁寧に説明していくつもりです。 ...
http://qiita.com/jnchito/items/640f17e124ab263a54dd


例えばユーザーのFacebook情報を取得するとき、FacebookAPIにリクエストが発生したら予め用意したニセモノのプログラムを呼ぶようにすることが出来ます。

また「aが呼ばれたときに本当はbを返すのだけど、ここのテストだけはcを返したい」というときに使用したりもします。


つまりモックとは、外部APIなどテストを行うために必要だけれど使用できない、再現することが難しい場合に、その役割を担ってくれるものです。


ちなみにモックとスタブの違いは?

モックと似た言葉にスタブというものがあります。気になって調べてみたのですが、両者の違いは使用目的だそうです。基本的にどちらもニセモノを作り出すことには変わらないようです。


ただその違いを明確に理解するのはなかなか難しく、またあまり意識する必要もないという意見もあったので、今回は保留にしました。時間があるときに色々と調べてみようと思います。


ちなみに、分かりやすく書いてある記事があったので、載せておきます。


「スタブ」と「モック」は全然違うものなんですよ - uehaj's blog
「スタブ」と「モック」は全然違うものなんですよう、という話は前からされてますが、 世の中にたくさんの誤解があふれている。 ファウラー氏の記事 もわかりにくいわい!!!頭のいい人に解説させてはダメだ!(暴論)。 つーことで上の考え方を私の言葉で述べます。 「スタブ」と「モック」は違います。何が違うかといいますと、目的が違います。何の目的かというと、試験の目的です。 ...
http://uehaj.hatenablog.com/entry/20090427/1240815860


モックとスタブの違い
こんばんは。開発部 kuma です。先日社内勉強会でテスティングフレームワークの紹介があり、そこでモックとスタブの違いは何かについての話がありました。人から聞くのは2回目だか3回目だかになるのですが、
http://jp.corp-sansan.com/blog/hitokoto/2012/120122.html


モックの準備

`Omniauth`部分のテストに関しては以下に従っております。


omniauth/omniauth
omniauth - OmniAuth is a flexible authentication system utilizing Rack middleware.
https://github.com/omniauth/omniauth/wiki/Integration-Testing


まずモックにすべきところを整理しましょう。

今回はユーザーのFacebook情報を取得する際にFacebookAPIを用います。そしてFacebookに登録されている名前やEmailを取得します。

そのため、今回モックにするところはFacebookAPIにリクエストがあったときに返す部分です。

以下をHelperに記します。

def facebook_mock(name, email)
  OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new(
    provider: 'facebook',
    uid: 1234567890,
    info: {
      name: name,
      email: email
    },
    credentials: {
      token: 'hogepiyo1234'
    }
  )
end

OmniAuth.config.test_mode = true


たとえば、`facebook_mock('foo', 'bar')`とすれば、以下の値が得られます。

{ provider: 'facebook', uid: 1234567890, info: { name: 'foo', email: 'bar' } , credentials: { token: 'hogepiyo1234' } }


また`OmniAuth.config.test_mode = true`はOmniauthを用いたテストの際に必要になるので、一緒に記述しておいてください。これを記述すると、FacebookAPIにリクエストが送られそうになると、それを中止してすぐにコールバックしてくれます。

RSpec

では、Facebookログイン部分の一連のテストを書いていきます。


まず、ユーザーを作成します。

let(:user) { User.create(name: 'hoge', email: 'hoge@hoge.com') }


テストの前に`OmniAuth.config.mock_auth[:facebook]`を初期化し、`facebook_mock`をセットします。

OmniAuth.config.mock_auth[:facebook] = nil
Rails.application.env_config['omniauth.auth'] = facebook_mock(
  name: user.name,
  email: user.email
)


準備はこれだけです。では実際にFacebookログインをしてみます。今回は分かり易くボタンを押してFacebookログインをする形式にしてみました。

click_link 'Facebookを利用してログインする'


さて、ボタンが押されると通常はFacebookAPIにリクエストが走りますが、テストではすぐにコールバックされます。

ただモックのおかげで、`request.env['omniauth.auth']`には下記の値が入っております。

{ provider: 'facebook', uid: 1234567890, info: { name: 'hoge', email: 'hoge@hoge.com' } , credentials: { token: 'hogepiyo1234' } }


そのため、`request.env['omniauth.auth']['info']`で`name: 'hoge', email: 'hoge@hoge.com'`の組み合わせを取得できるようになります。あとはこれをDBと照合して、有効であるかどうかを確かめればテスト終了です。


テスト全体は以下のようになります。

discribe 'login via Facebook' do
  let(:user) { User.create(name: 'hoge', email: 'hoge@hoge.com') }

  before do
    OmniAuth.config.mock_auth[:facebook] = nil
    Rails.application.env_config['omniauth.auth'] = facebook_mock(
      email: user.email,
      name: user.name 
    )
    click_link 'Facebookを利用してログインする'
  end

  it 'should succeed' do
    expect(page.status_code).to eq 200
  end
end


ちなみに検証部分がステータスコードの判別しかないですが、ログインされているかどうかを簡単に確認できる指標が欲しいですね。

例えば、`expect(current_user).to eq user`のようなものがあれば。。


以上、Mockを使ったRspecの書き方でした。読んで頂きありがとうこざいました。

アドバイスなどありましたら是非お願いします!


We're hiring!


Cluexではビジネスサイド、エンジニアサイド共にメンバーを募集しています!

お気軽にご連絡下さい!


Railsエンジニア
急増するトラフィックに耐えうるサービスを一緒に作るRailsエンジニア募集
Cluexは、 「IT×教育で世の中を変える」をテーマに、子育てをするママの情報格差をなくすべくmamanokoを開発している会社です。 妊娠・出産・育児・子育てをするママのための情報メディア「mamanoko」 https://mamanoko.jp/ 「mamanoko for iOS」 http://apple.co/2dwojlD 「子育ての情報格差を無くす」というミッションに向かってサービスを開始し、まず、第一弾として子育てを応援するウェブサービスに特化しています。 利用者は「妊娠、出産を控えるプレママ、子育て中のママ」で、主に25~40歳までの女性ユーザーが愛用中。 「子育て」に必須なサービスとして、今最も注目を集める「ママ」向け媒体として急成⻑し続けています。
株式会社クルイト


Ruby on Rails
新しい技術をどんどん触っていきたいRailsエンジニアWanted!
◆MISSION◆ 世界の社会問題を解決する 21世紀となった現代でも尚、 世界中で飢餓や貧困、戦争が起こっています。 この地球上で起きるあらゆる社会問題を解決できるのは唯一、人です。 そして、人を創るのは「教育」です。 「教育」の改革こそが、世界中のあらゆる社会問題の解決と人類の更なる発展に繋がると考えています。 世界中の子どもたちが平等な教育を受ける社会。 一人ひとりの可能性を広げることができる社会。 クルイトは、そんな社会の実現を「教育」の力で目指します。 ◆VISION◆ 「教育」で世界を変える。 この大学に行けば安泰だ。この企業に入れば必ず幸せになれる。 そういった「王道ルートを通ればよい」と考えられていた時代から、 正解のない時代へと変化しつつあります。 選択肢が増え、幸せの形が多様化し、自分で考えてつかみ取らなければならない、 個人の力が試される時代です。 しかし、こんなにもどんどん世の中が変化しているのに、教育の形は戦後からほとんど変わっていません。 考え方も価値観も違うはずの生徒たちが一つの教室に押し込まれ、一斉に同じ授業を受けています。同質で、受動的に知識を詰め込まれる教育です。 私たちは、そんな教育課題をビジネスを通じてアップデートし、社会問題の解決につながる人材を育成していきたいと考えています。 ◆SERVISE◆ ・キミノスクール:「自律した子供を育てる」ことに特化した学習塾 ・武田塾    :「授業をしない」ことが特徴の大学受験予備校 ・ままのて   :子育て総合メディア/アプリサービス ・塾み〜る   :全国の学習塾検索Webサービス ◎「自律した子供を育てる」学習塾:キミノスクール 「キミノスクール」の一番の目的は、テストでいい点を取ったりすることではありません。勉強ができるようになることも、受験に成功することも、人生を豊かにするための一手段にすぎません。大切なのはその先、自立した大人になって社会へ飛び立ち、活躍できる人材になることです。 キミノスクールでは、従来とは異なったコーチングやアクティブラーニングといった手法を用いて、自ら未来を切り開くことのできる自律した子供の育成を目指します。 オンライン/オフラインの両方で学習塾を運営しています。 一般的な塾とキミノスクールの違いは「子供たちが自分で決める」ことを重要視している点です。「人生の目的」を持つことが重要であると考えており、既存の学習塾の概念とは異なった、新しい学習塾の在り方を追い求めています。 ◎「授業をしない」ことが特徴の大学受験予備校:武田塾 生徒の自学自習を支援する大学受験予備校です。偏差値を上げるためには「わかる・やってみる・できる」の3ステップが必要ですが、授業では「わかる」までしかやらないため、授業を受けるだけでは成績に結びつきません。やってみる・できるのステップまでフォローすることで、本当の意味での学習理解度を高めます。大学受験を通して、自分で考え、決断し、自走する力のある人を育てます。 偏差値が30台だった学生を1年で難関大学への逆転合格へ導いた例も多数あります。 ◎子育て総合メディア/アプリサービス:ままのて(子育て支援サービス事業) 「ままのて」は子育てに悩む全ての方へ寄り添うべく運営されているアプリです。 今後は機能を追加し、日本の子育てメディア/アプリシェアNo.1を目指しています。 子供の教育は、民間教育(学習塾など)・学校教育・家庭教育の三つの要素から成り立っています。 「ままのて」は家庭でのよりよい教育のヒントを提供出来るようにするために開発されました。家庭では子供が最も多くの時間を過ごすため、民間・学校の教育がより良いものになったとしても、家庭教育が疎かである場合、最大限の効果は発揮できないと考えています。そのため、育児/教育メディアを運営を行い、家庭教育へのアプローチを続けています。 ◎全国の学習塾検索アプリサービス:塾み〜る(教育事業者向けITソリューション事業) 「塾み〜る」は全国の小中高生/保護者と学習塾を繋げるためのサービスです。 全国の学習塾へ「塾み〜る」への情報掲載を依頼するだけでなく、クルイトがこれまで得た学習塾経営ノウハウを活かして、日本の教育事業をアップデートするべくさまざまなご提案も行います。具体的には、Webマーケティング、その他のコンサルティングサービスを提供することにより、その学習塾がより良くなっていくような提案をしております。 幅広いソリューションをもって幅広いソリューションをもって、ゆりかごから受験までをフルサポートします。
株式会社クルイト


PM・Webディレクション
IT×教育で教育格差を無くす!事業を加速してくれるWebディレクター募集
Cluexは、 「IT×教育で世の中を変える」をテーマに設立されました。 世界では貧困、飢餓、紛争、資本主義による格差が起きています。世界に存在するこういった大きな問題を解決していくのは人です。そして人を育てる教育こそが世界の不平等を救うことになります。 現在は第一弾として、"子育ての情報格差を無くす"ためにママ向けメディアのmamanokoを開発しています。 https://mamanoko.jp/ 利用者は「妊娠、出産を控えるプレママ、子育て中のママ」で、主に25~40歳の女性ユーザーが愛用中。 「子育て」に必須なサービスとして、今最も注目を集める「ママ」向け媒体として急成⻑し続けています。
株式会社クルイト


セールス・事業開発
世界の教育格差を無くす!子育てメディアの広告事業立ち上げ責任者wanted
Cluexは、 「IT×教育で世の中を変える」をテーマに設立されました。 世界では貧困、飢餓、紛争、資本主義による格差が起きています。世界に存在するこういった大きな問題を解決していくのは人です。そして人を育てる教育こそが世界の不平等を救うことになります。 現在は第一弾として、"子育ての情報格差を無くす"ためにママ向けメディアのmamanokoを開発しています。 https://mamanoko.jp/ 利用者は「妊娠、出産を控えるプレママ、子育て中のママ」で、主に25~40歳の女性ユーザーが愛用中。 「子育て」に必須なサービスとして、今最も注目を集める「ママ」向け媒体として急成⻑し続けています。
株式会社クルイト


参考文献


http://qiita.com/jnchito/items/640f17e124ab263a54dd

http://jp.corp-sansan.com/blog/hitokoto/2012/120122.html

http://uehaj.hatenablog.com/entry/20090427/1240815860

https://github.com/omniauth/omniauth/wiki/Integration-Testing

株式会社クルイトでは一緒に働く仲間を募集しています
9 いいね!
9 いいね!

今週のランキング

神山 奎吾さんにいいねを伝えよう
神山 奎吾さんや会社があなたに興味を持つかも