How to test ElasticSearch in a Rails application (Rspec)

Robin picture Robin · Mar 13, 2012 · Viewed 13.1k times · Source

I was wondering how you were testing the search in your application when using ElasticSearch and Tire.

  • How do you setup a new ElasticSearch test instance? Is there a way to mock it?

  • Any gems you know of that might help with that?


Some stuff I found helpful:

I found a great article answering pretty much all my questions :)

http://bitsandbit.es/post/11295134047/unit-testing-with-tire-and-elastic-search#disqus_thread

Plus, there is an answer from Karmi, Tire author.

This is useful as well: https://github.com/karmi/tire/wiki/Integration-Testing-Rails-Models-with-Tire

I can't believe I did not find these before asking...

Answer

spaudanjo picture spaudanjo · Mar 14, 2012

Prefixing your index-names for the current environment

You could set a different index-name for each environment (in your case: the test environment).

For example, you could create an initializer in

config/initializers/tire.rb

with the following line:

Tire::Model::Search.index_prefix "#{Rails.application.class.parent_name.downcase}_#{Rails.env.to_s.downcase}"

A conceivable approach for deleting the indexes

Assuming that you have models named Customer, Order and Product, put the following code somewhere at your test-startup/before-block/each-run-block.

# iterate over the model types
# there are also ways to fetch all model classes of the rails app automaticly, e.g.:
#   http://stackoverflow.com/questions/516579/is-there-a-way-to-get-a-collection-of-all-the-models-in-your-rails-app
[Customer, Order, Product].each do |klass|

  # make sure that the current model is using tire
  if klass.respond_to? :tire
    # delete the index for the current model
    klass.tire.index.delete

    # the mapping definition must get executed again. for that, we reload the model class.
    load File.expand_path("../../app/models/#{klass.name.downcase}.rb", __FILE__)

  end
end

Alternative

An alternative could be to set up a different ElasticSearch instance for testing on another port, let's say 1234. In your enviornment/test.rb you could then set

Tire::Configuration.url "http://localhost:1234"

And at a suitable location (e.g. your testing startup) you can then delete all indexes on the ElasticSearch testing-instance with:

Tire::Configuration.client.delete(Tire::Configuration.url)

Maybe you must still make sure that your Tire-Mapping definitions for you model classes are still getting called.