- 更新日: 2014年1月7日
- RSpec
Rails + Devise + OmniAuth で Facebook/Twitter の OAuth 認証を RSpec + Capybara でインテグレーションテスト(RequestSpec)
Rails4 アプリケーションで、Devise + OmniAuth により認証システムを構築し、Facebook/Twitter の OAuth 認証に対して、RSpec + Capybara でインテグレーションテスト(RequestSpec)を行います。OAuth 認証用のモックを使用します。
以下の公式Wikiを中心に進めました。
Integration Testing – omniauth
また、Devise と Omniauth を使っての認証の実装と仕様は以下。
Rails4 で Devise と OmniAuth で、Twitter/Facebook のOAuth認証と通常フォームでの認証を併用して実装 | EasyRamble
Rails4 で Devise と OmniAuth を使い、通常フォームでのユーザー登録・サインインと OAuth 認証を併用する仕様を考えた | EasyRamble
— 環境 —
rails-4.0.1
devise-3.2.2
omniauth-1.1.4
rspec-rails-2.14.0
capybara-2.2.0
公式Wikiを読んで、要点の和訳
OmniAuth.config.test_mode
1 |
OmniAuth.config.test_mode = true |
OmniAuth へのリクエストがモックによる認証となり、/auth/provider へのリクエストが即座に、/auth/provider/callback へとリダイレクトされる。
OmniAuth.config.mock_auth
1 2 3 4 5 |
OmniAuth.config.mock_auth[:twitter] = OmniAuth::AuthHash.new({ :provider => 'twitter', :uid => '1234' # etc. }) |
mock_auth にインテグレーションテストで使われる、モック用の認証ハッシュをセットします。:default のハッシュキーを使うと、プロバイダーが指定されない場合のデフォルトを指定できる。
OmniAuth.config.add_mock
1 |
OmniAuth.config.add_mock(:twitter, {:uid => '1234'}) |
add_mock メソッドを使うと、モックに新たな要素を追加でき、デフォルトの認証ハッシュとマージされます。
Mocking Failure
1 |
OmniAuth.config.mock_auth[:twitter] = :invalid_credentials |
mock_auth にハッシュでなくシンボルを指定すると、次のメッセージとともに認証が失敗します。”You will be redirected back to /auth/failure?message=invalid_credentials”
Setting up the controller
ルーティングのエラーを回避するために、以下を設定します。
1 2 3 4 |
before do request.env["devise.mapping"] = Devise.mappings[:user] request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:twitter] end |
OmniAuth によるログイン用ヘルパーを定義
ここから、テスト準備用のコードを書きます。まずは、omniauth 認証用のヘルパー(set_omniauth, login_with_omniauth)を作成したりなど。set_omniauth が OAuth 認証テスト用の準備やモックをセットするメソッド。login_with_omniauth が OAuth 認証URLにアクセスして認証させるメソッドです。
app/spec/support/request_helpers.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
include Warden::Test::Helpers module RequestHelpers def login(user) login_as user, scope: :user end def set_omniauth(service = :twitter) OmniAuth.config.test_mode = true OmniAuth.config.mock_auth[service] = OmniAuth::AuthHash.new({ provider: service.to_s, uid: '1234' }) case service when :facebook OmniAuth.config.add_mock(service, { info: { email: "#{service.to_s}_oauth_user@example.com" }, extra: { raw_info: { name: "#{service.to_s}_oauth_user" } } } ) when :twitter OmniAuth.config.add_mock(service, { info: { nickname: "#{service.to_s}_oauth_user" } } ) end OmniAuth.config.mock_auth[service] end def login_with_omniauth(service = :twitter) visit "/users/auth/#{service.to_s}" end end |
spec/spec_helper.rb
続いて、spec_helper.rb にて作成した、RequestHelpers モジュールを include。
spec/spec_helper.rb
1 2 3 4 5 |
RSpec.configure do |config| # ・・・ config.include RequestHelpers, :type => :request end |
RequestSpec
続いて、インテグレーションテストを生成してテストコードを書く。
1 2 3 |
$ bundle exec rails generate integration_test omniauth_pages |
spec/requests/omniauth_pages_spec.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
require 'spec_helper' describe "Omniauth pages" do subject { page } describe 'with facebook oauth' do context "valid oauth signin when facebook email doesn't exist" do let(:oauth_user) { set_omniauth(:facebook) } before do login_with_omniauth(oauth_user.provider) end let(:user) { User.where(:provider => oauth_user.provider, :uid => oauth_user.uid).first } specify { expect(user).not_to eq nil } specify { expect(user.provider).to eq oauth_user.provider } specify { expect(user.uid).to eq oauth_user.uid } specify { expect(user.name).to eq oauth_user.extra.raw_info.name } specify { expect(user.email).to eq oauth_user.info.email } # 以下省略 |
以上です。
- – 参考リンク –
- Integration Testing · intridea/omniauth Wiki · GitHub
- Testing Omniauth with Devise, Rspec and Capybara
- Easy Rails OAuth Integration Testing
- Rails3, OmniAuth, RSpec, Capybaraでログインユーザのモック | ツボニチ
- Test Omniauth Facebook Callback Controllers in Devise with rspec
- omniauth wiki
- RSpec の関連記事
- FactoryGirlをSpringと共に使う時の注意
- 複数モデルのpost :createをテストするRSpecコード(Controller Spec)
- RSpec3でTime.nowをスタブ化(stub)
- RSpecでJSONによるPOSTリクエストをテスト
- RSpec & Capybara の雑感
- RSpec+Capybaraで同名の複数要素の並び順をテストする
- RSpec3ではrails_helper.rbがrequireされる
- Capybara + Launchy で RSpec テストをブラウザで確認
- CapybaraのwithinをRSpecで使う
- Serverspec(RSpec)のテスト出力に色を付けて見やすくフォーマット
Leave Your Message!