LoginSignup
8
3

More than 5 years have passed since last update.

Geocoderをrspecでテストするときのstubの書き方

Last updated at Posted at 2017-05-03

概要

Geocoder.search('検索キー')

をrspecのテストで使いたいとき、stubは以下の通り。

before do
    Geocoder.configure(lookup: :test)
    Geocoder::Lookup::Test.add_stub('検索キー',[検索結果のハッシュ])
end

説明

stubを使わなかった時のエラー例

Geocoder.search('検索キーワード')を使ったコードに対して、ネットワーク接続が出来ない環境でrspecを実行するとエラーがでる。

これは、git geocoderに書かれているとおり、'検索キーワード'に対応するstubを作れば解決する。
以下に、解決例を書く。

解決例

シナリオ

place_search_controllerというコントローラに /place_search/?keyword=東京 のルーティングでアクセスし、keywordを元にGeocode.search(keyword)を使う機能を実装後、テストコードを書く。

実装した機能

Geocoderを使ってkeywordで検索したとき、#indexは以下の結果を返す

  • 結果が得られればステータス200でview(views/place_search/index.html.erb)を表示
  • 結果が得られなければステータス500でview(errors/error_500.html.erb)を表示する
app/controllers/place_search_controller.rb
class PlaceSearchController < ApplicationController
    def index
        geo = Geocoder.search(params[:keyword])
        if geo.present?
            @location = Geocoder.search(params[:keyword])[0].data["geometry"]["location"] # latitudeとlongitudeを取得して、viewで使うことを想定した動き(viewは省略)
        else
            render template: 'errors/error_500', status: 500, layout: 'application', content_type: 'text/html' # 検索ヒットが0件の時は 500番を返す
        end
    end
end

rspecテストコード

  • keyword="東京"で検索したときはステータス200番を返す
  • keyword="ダメなキーワード"で検索したときはステータス500番を返す

上記2点をテストするコードは以下の通り

spec/controllers/place_search_controller_spec.rb
require 'spec_helper'

describe PlaceSearchController do
    describe '#index' do
        before do
            Geocoder.configure(lookup: :test)
            Geocoder::Lookup::Test.add_stub(
                '東京', [{
                'geometry' => { 'location' => { 'lat' => 35.7090259, 'lng' => 139.7319925 } }
            }]
            )
            Geocoder::Lookup::Test.add_stub(
                'ダメなキーワード', []
            )
        end
        it '東京で検索したときはステータス200番を返す' do
            get '/place_search', {keyword: '東京'}
            expect(response.status).to eq 200

        end
        it 'ダメなキーワードで検索したときはステータス500番を返す' do
            get '/place_search', {keyword: 'ダメなキーワード'}
            expect(response.status).to eq 500
        end
    end
end

これでOK。

解説

Geocoder.search('検索キー')は、検索キーを位置情報API(初期値はgoogle)に問い合わせることで位置情報を得ています。よって、外部ネットワークに接続できない場合はGeocoder.searchが機能しないため、関連するテストコードが全てエラーとなります。
テストのためだけに、外部ネットワークに無駄にアクセスすることは推奨されないため、CI環境では外部へのネットワーク接続が不可の場合があります。
このときに使うのがstubという仕組みであり、Geocoderではすでにその仕組みを用意していますので、活用するだけです。

Geocoder.configure(lookup: :test)

lookupは検索するapiを設定するためのキーです。これをtestと指定することにより、以降のGeocoder.searchが以下で示すstubに対して行われるようになります。

Geocoder::Lookup::Test.add_stub('東京', [ 省略 ])

stubを指定します。フォーマットは、 Geocoder::Lookup::Test.add_stub('検索キー',[検索結果のハッシュ]) です。
検索キーは Geocoder.search('東京') であれば 東京 です。
検索結果のハッシュは、Geocoder.configureの設定によって異なります。わからない場合は、 rails c で 下記のコマンドを実行してその結果を入れてください。

> Geocoder.search('検索キー')[0].data.to_hash

例えば検索キーとして 東京 を指定した場合は以下の通りなので、それを検索結果のハッシュとして貼り付ければstubとして使えます。(以下は見やすいように整形しています。)

Geocoder.search('東京')[0].data.to_hash
{ 'address_components' => [{ 'long_name' => 'Tokyo',
                             'short_name' => 'Tokyo',
                             'types' => %w(colloquial_area locality political) },
                           { 'long_name' => 'Tokyo', 'short_name' => 'Tokyo', 'types' => %w(administrative_area_level_1 political) },
                           { 'long_name' => 'Japan', 'short_name' => 'JP', 'types' => %w(country political) }],
  'formatted_address' => 'Tokyo, Japan',
  'geometry' => { 'bounds' => { 'northeast' => { 'lat' => 35.8175167, 'lng' => 139.9198565 },
                                'southwest' => { 'lat' => 35.5208603, 'lng' => 139.5629048 } },
                  'location' => { 'lat' => 35.7090259, 'lng' => 139.7319925 },
                  'location_type' => 'APPROXIMATE',
                  'viewport' => { 'northeast' => { 'lat' => 35.8175167, 'lng' => 139.9198565 },
                                  'southwest' => { 'lat' => 35.5208631, 'lng' => 139.5629048 } } },
  'place_id' => 'ChIJXSModoWLGGARILWiCfeu2M0', 'types' => %w(colloquial_area locality political) }


なお、検索結果のハッシュは機能から呼び出している箇所の指定だけでもいいです(もちろん全部書いてもいいですが、冗長ですよね)。今回の機能では、'location'の箇所しか呼び出していないので、以下箇所だけstubに記述しました。

Geocoder::Lookup::Test.add_stub(
                '東京', [{
                'geometry' => { 'location' => { 'lat' => 35.7090259, 'lng' => 139.7319925 } }
            }]
            )
8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3