RSpec and Sunspot

calaveraDeluxe edited this page Feb 24, 2017 · 14 revisions

Stubbing out Sunspot during testing

If you want to prevent any test from running a Solr search, which you probably do, you can do so within your spec_helper.rb as opposed to having to do it in lots of describe blocks. The code below has been tested and works with sunspot/sunspot-rails v1.0.3.

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

Note: This does not work with Sunspot v 1.1.0. Instead, create a file called sunspot.rb in the spec/support folder, with the following line:

Sunspot.session = Sunspot::Rails::StubSessionProxy.new(Sunspot.session)

Note that if you’re using will_paginate, your code may break, because Sunspot.search.results will be an empty array instead of a WillPaginate::Collection.

Running Sunspot during testing

Unit tests should not touch Solr. If you want to test Solr do so in integration tests with something like Steak or Cucumber.

Check out the read me for lots of links to great articles on testing Solr within your application.

If you want to do it anyway, here’s how

It’s also possible to start up a Solr instance for tests. This is what I came up with for v1.1.0 and Rails v2.3.8 (adapted from this blog post and this one):

You may want to add the following helper under spec/support/

$original_sunspot_session = Sunspot.session
Sunspot.session = Sunspot::Rails::StubSessionProxy.new($original_sunspot_session)

module SolrSpecHelper

  def solr_setup
    unless $sunspot
      $sunspot = Sunspot::Rails::Server.new

      pid = fork do
        STDERR.reopen('/dev/null')
        STDOUT.reopen('/dev/null')
        $sunspot.run
      end
      # shut down the Solr server
      at_exit { Process.kill('TERM', pid) }
      # wait for solr to start
      sleep 5
    end

    Sunspot.session = $original_sunspot_session
  end
end

Now, if you want to actually test the sunspot behavior rather than stubbing it, you should be able to call solr_setup before all your rspec examples for a given specific file:

require 'spec_helper'


describe YourModel do
  include SolrSpecHelper

  before(:all) do
    solr_setup
  end

  after(:all) do
    YourModel.remove_all_from_index!
  end

  describe "something" do
    it "should so somenthing" do
      #...
    end
  end
end

Note that this works even if you have a Solr instance running for development, because Sunspot::Rails::Server is smart enough to create a different instance based on RAILS_ENV.

“Why not use Sunspot::Rails::Server.new.start, which spins off its own process and manages a pid file?” you might ask. Well, because something about the way it forks screws up Rails. Somehow it ends up running all the tests twice, with ActiveRecord’s database connection broken for half of them.