LoginSignup
5
5

More than 5 years have passed since last update.

Sunspot(Rails) の検索結果をrspecでテストするためにstubする

Posted at

概要

RailsでSolrが楽に使えるライブラリ、 sunspot_rails の検索結果をRSpecで偽装するためにstubを使うやりかた

だいたい以下のバージョン

  • Ruby 2.2.0
  • Rails 4.2.3
  • RSpec 3.3.2
  • Sunspot 2.2.0

前提

公式によると、以下のようにしましょうってことなので、まずはコレに従う。

require 'sunspot/rails/spec_helper'

RSpec.configure do |config|
  config.before(:each) do
    ::Sunspot.session = ::Sunspot::Rails::StubSessionProxy.new(::Sunspot.session)
  end

  config.after(:each) do
    ::Sunspot.session = ::Sunspot.session.original_session
  end
end

実例

RSpec::Mocks.with_temporary_scope do
  search = Hoge.search
  record = FactoryGirl.build(:hoge)
  # Hogeは適当に置き換えましょう。 FactoryGirlじゃなくfixture使ってたらそっちで。 scoreの数字は何でもいい。
  raw_hit = {"id"=>"#{record.class.to_s} #{record.id}", "score"=>7.265403}
  hit = Sunspot::Search::Hit.new(raw_hit, nil, search)
  hit.instance_variable_set(:@result, record)
  allow_any_instance_of(Sunspot::Rails::StubSessionProxy::Search).to receive(:hits).and_return([hit])
  allow_any_instance_of(Sunspot::Rails::StubSessionProxy::Search).to receive(:results).and_return([record])

  # 何かsunspotに依存した処理をして・・
  YourSearchManager.search_hoge
  # あとは自由にexpectationを書こう!
end

each_hit_with_results を使いたければ rails_spec の適当なところに以下のコードを書いておくとよいです。

class Sunspot::Rails::StubSessionProxy::Search
  def each_hit_with_result
    return unless block_given?
    hits.each do |hit|
      yield(hit, hit.result)
    end
  end
end

こんな感じで書くと良さげでした。 RSpec::Mocks.with_temporary_scope がないと、同じスコープ内で別のitemをテストしようとするとコケるし、イディオム的に入れておきました。
このブロック内だけのシンプルなexpectationなら、外しちゃっても良いでしょうね。

allow_any_instance_of がグローバル過ぎて気持ち悪いって人は、適当な所でメソッドを切り分けて、代わりに以下のようにしてstub化したsearchを返すようにするとよいです。(僕はそうしてる)

allow(search).to receive(:hits).and_return([hit])
allow(search).to receive(:results).and_return([hoge])
expect(YourSearchManager).to receive(:search_hoge).and_return(search)
5
5
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
5
5