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!
【ビジョン】 株式会社クルイトでは「教育で世界を熱狂させる」というビジョンのもとに 学習塾、学校、子育ての情報サイトなどを運営しています。 今の時代に合った新しいカタチの教育サービスを届けることで 本当に自分の好きな人生を歩んでいる「人生に熱狂している人」を増やします。 【サービス】 ・キミノ高等学院:「自分のことをもっと好きになる」通信制高校 ・キミノスクール:「自律した子を育てる」学習塾 ・武田塾    :「授業をしない」学習塾 ・ままのて   :妊娠/子育てに関する情報メディア ◆キミノ高等学院◆ キミノ高等学院は「自分のことをもっと好きになる」ことができる通信制高校です。 「全員が同じ教室で、同じ授業を受け、同じ基準で評価される」という従来の学校教育では、 それに合わない子は「自分はダメだ」と感じて自信をなくし、人によっては不登校になってしまいます。 しかし、問題があるのは子どもたちではなく、教育システムです。 私たちキミノ高等学院では、 ・1対1で生徒の進路や学力に合わせた個別指導 ・5教科以外の興味関心を広げるワークショップ ・本当に自分のやりたいことが見つかる進路相談 などによって、 従来の学校教育には合わなかった子でも、 自分の強みや得意に気づき、 本当に自分が進みたい道を見つけることができるようになります。 キミノ高等学院を広げていくことで、 「一人ひとりに合った最適な教育」が当たり前になる世の中を目指しています。 ◆キミノスクール◆ キミノスクールは「自律した子を育てる」中学生・高校生向けの学習塾です。 「そもそも勉強のやる気がない」 「何をしていいかわからない」 「自分にはどうせ難関大は無理だ」 と感じている子でも、 頑張り方を学び、勉強習慣をつけ、志望校に合格し、 「自分でもやればできるんだ!」と成功体験を積んでもらえることを目標にしています。 ・コーチングを軸としたやる気を高める個別指導 ・AIを活用した効率的な学習環境の提供 ・「大学進学」のその先を見据えたキャリア教育 などにより、どんな子でも勉強が好きになり、 卒業後も自分の好きな人生を歩めるサポートをしていきます。 ◆武田塾◆ 武田塾は、「授業をしない」を特徴とした大学受験向け学習塾です。 偏差値40台・E判定からでも逆転合格できる独自の勉強法で、 「今の成績は良くないけど難関大に合格したい!」という生徒をサポートします。 大学受験の勉強を通して、 「目標達成のために、自分で考え、自分で行動する」という経験を積むことで、 卒業後も役に立つ「自学自習」の習慣が身につきます。 ◆ままのて◆ ままのては、初めての妊娠/育児でお困りのママ・パパのための情報メディアです。 「教育」と聞くと「学校」や「学習塾」が思い浮かびますが、 お子様に一番影響があるのはご家庭で一緒に過ごす親による教育です。 しかし、誰も「子育て」については教えてくれないので、 「本当にこれで良いのかな?」と不安を抱いてる方は少なくありません。 ままのてでは、妊娠、出産、その後の育児に関する情報を提供することで、 ママやパパが安心して子育てができるようになることを目指しています。 親であるママやパパが自信を持って子育てをできれば、 そんなご家庭で育ったお子様も伸び伸び育つことができると考えています。
株式会社クルイト


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 いいね!

今週のランキング

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