Unit & Integration Testing Solr w/ RSpec, sunspot_solr, sunspot_test & sunspot_matchers

The sunspot_test gem allows you to add a tag to a describe/context block automatically starting and stopping a Solr instance within that context.

describe "searching", search: true do
# some code
end

The sunspot_matchers gem provide custom RSpec matchers that you can use to verify that the search you are running using sunspot is correct.

The goal of these matchers are to make it easier to unit test search logic without having to construct the individual fixture scenarios inside of Solr and then actually perform the search against Solr

The gem essentially decorates the Sunspot.session to intercept calls made to it. In order to use it you will have to add the following to your spec_helper.rb file:

config.before do
  Sunspot.session = SunspotMatchers::SunspotSessionSpy.new(Sunspot.session)
end

This is perfect for unit tests since they will not need an actual Solr instance to work and therefore will be much faster. You use the custom RSpec matchers such as be_a_search_for or have_search_params to verify that the Solr query your code will execute is correct. Then, in your integration tests you can actually do an end to end test with an instance of Solr.

This is exactly what I set out to do, however the config.before block in the spec_helper.rb file intercepted the Sunspot.session and always returned an empty array (even in integration tests). Since I was using the sunspot_test gem which requires adding a tag (search: true) to your describe block I used the following approach to tell RSpec that for these tagged blocks use the actual Solr.session.

config.before do
  Sunspot.session = SunspotMatchers::SunspotSessionSpy.new(Sunspot.session)
end

# SunspotMatchers will keep a reference to the original session so we can access it like so
config.before(:each, search: true) do
  Sunspot.session = Sunspot.session.original_session
end

In this way, anytime we tag a block with search: true we will be using the actual Solr session. Hope this helps someone :-).

Advertisements