1
/
5

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

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

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

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

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


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

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

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


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

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


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

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


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

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


モックとは何か。

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



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

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


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


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

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


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


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




モックの準備

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



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

今回はユーザーの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ではビジネスサイド、エンジニアサイド共にメンバーを募集しています!

お気軽にご連絡下さい!



Ruby on Rails
新しい技術をどんどん触っていきたいRailsエンジニアWanted!
◆「教育」という切り口から世界の社会問題の解決へ多角的にアプローチしています クルイトは「教育」で「世界の社会問題を解決」するべく事業展開しています。 具体的には、メディア/アプリ事業と民間教育事業を軸としてサービス提供を行なっています。 現在は、下記3つの事業に注力しています。 ・ままのて   :子育て総合メディア/アプリサービス ・塾み〜る   :全国の学習塾検索Webサービス ・キミノスクール:「自律した子供を育てる」に特化したオンライン/オフライン学習塾 ◆子育て総合メディア/アプリサービス:ままのて(子育て支援サービス事業) 「ままのて」は子育てに悩む全ての方へ寄り添うべく運営されているアプリです! 今後は機能を追加し、日本の子育てメディア/アプリシェアNo.1を目指しています。 子供の教育は、民間教育(学習塾など)・学校教育・家庭教育の三つの要素から成り立っています。 「ままのて」は「子供が最も多くの時間を過ごす家庭」でより良い教育を提供出来るようにするために開発されました。民間・学校の教育がより良いものになったとしても、「家庭教育」が疎かである場合、最大限の効果は発揮できないと考えています。そのため、育児/教育メディアを運営を行い、家庭教育へのアプローチを続けています! ◆全国の学習塾検索アプリサービス:塾み〜る(教育事業者向けITソリューション事業) 「塾み〜る」は全国の小中高生/保護者と学習塾を繋げるためのサービスです。 全国の学習塾へ「塾み〜る」への情報掲載いただくアプローチはもちろんですが、クルイトがこれまで得た学習塾経営ノウハウを活かして、日本の教育事業をアップデートするべくさまざまなご提案も行います。具体的には、Webマーケティング、その他のコンサルティングサービスを提供することにより、その学習塾がより良くなっていくような提案をしております。 クルイトは、世界の社会問題を解決すべく「教育」に焦点を当てたアプローチをしております。そして、塾み〜る 以外 のクルイトの事業で直接的に子供たちを教育をしています。そしてその学習塾で最適な教育を受けていただきたい、という思想を持っています。 ◆「自律した子供を育てる」に特化したオンライン/オフライン学習塾:キミノスクール 「キミノスクール」は、従来とは異なった「コーチング」や「アクティブラーニング」といった手法を用いて、自ら未来を切り開くことのできる自律した子供の育成を目指してオンライン/オフラインで学習塾を運営しております。 一般的な塾とキミノスクールの違いは「子供たちが自分で決める」ことを重要視している点です。「人生の目的」を持つことが重要であると考えており、既存の学習塾の概念とは異なった、新しい学習塾の在り方を追い求めています。 現在は、千葉県津田沼に1教室を構えており、今後は主にオンライン学習塾の展開を進めて行きます。講師と生徒が反対になって授業を行う反転授業などさまざまなコンテンツから主体性を持った子供の育成のために順調に拡大しています。
株式会社クルイト


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

株式会社クルイトでは一緒に働く仲間を募集しています
10 いいね!
10 いいね!
今週のランキング