Search code examples
ruby-on-railstestingrspecfactory-botsearchkick

RSpec: invalid model with searchkick


I'm not very sure I'm doing it right, but I have two models: House that has_one Address.

The Address model has:

class Address < ApplicationRecord
  searchkick
  belongs_to :house
end

I'm trying to test my house_controller with RSpec like this

RSpec.describe HousesController do
 context 'GET #index' do
 before { get :index }
 it     { is_expected.to render_template('index') }

 it 'assigns @houses' do
  h = create(:house)
  expect(assigns(:houses).results).to eq([h])
end
...

Nevertheless I always get a result which is not the one I expect. The code of my controller is the following:

def index
 if params[:term].present?
  @houses = House.search(params[:term])
 else
  @houses = House.search('*')
 end
end

I'm not sure I understand it, but could it be that since I'm using FactoryBot, it is creating lots of houses, and then when getting in the index method, there's a bunch of houses there and not only and precisely h?

This is my failure:

Failures:

  1) HousesController GET #index assigns @houses
     Failure/Error: expect(assigns(:houses).results).to eq([h])

       expected: [#<House id: 763, rent: 1173, deposit: 739, description: "Rerum cado curso curo alias.", preferred_ge...2018-11-26 21:40:43", available_at: "2018-12-17", user_id: 15945, lease_length: nil, built_in: nil>]
            got: [#<House id: 215, rent: 0.839e3, deposit: 0.797e3, description: "Rerum aeneus taceo crepusculum aestu...2018-11-26 21:17:53", available_at: "2018-12-17", user_id: 15776, lease_length: nil, built_in: nil>]

       (compared using ==)

       Diff:
       @@ -1,2 +1,5 @@
       -[#<House id: 763, rent: 1173, deposit: 739, description: "Rerum cado curso curo alias.", preferred_gender: 0, created_at: "2018-11-26 21:40:43", updated_at: "2018-11-26 21:40:43", available_at: "2018-12-17", user_id: 15945, lease_length: nil, built_in: nil>]
       +[#<House id: 215, rent: 0.839e3, deposit: 0.797e3, description: "Rerum aeneus taceo crepusculum aestus.", preferred_gender: 0, created_at: "2018-11-25 12:50:11", updated_at: "2018-11-25 12:50:11", available_at: "2018-12-16", user_id: 8065, lease_length: nil, built_in: nil>,
       + #<House id: 235, rent: 0.519e3, deposit: 0.642e3, description: "Cicuta totidem arbustum arcesso fugit tego.", preferred_gender: 0, created_at: "2018-11-25 12:54:28", updated_at: "2018-11-25 12:54:28", available_at: "2018-12-16", user_id: 8085, lease_length: nil, built_in: nil>,
       + #<House id: 648, rent: 0.668e3, deposit: 0.1104e4, description: "Corporis tametsi demens.", preferred_gender: 0, created_at: "2018-11-26 21:17:43", updated_at: "2018-11-26 21:17:43", available_at: "2018-12-17", user_id: 15775, lease_length: nil, built_in: nil>,
       + #<House id: 649, rent: 0.799e3, deposit: 0.611e3, description: "Ut ancilla tredecim.", preferred_gender: 0, created_at: "2018-11-26 21:17:53", updated_at: "2018-11-26 21:17:53", available_at: "2018-12-17", user_id: 15776, lease_length: nil, built_in: nil>]

     # ./spec/controllers/houses_controller_spec.rb:12:in `block (3 levels) in <top (required)>'

I'm starting with RSpec now and it's really taking me effort and hours to try to grab the grasp of it, thanks a lot in advance!


Solution

  • Searchkick docs about disabling indexing for tests with RSpec.

    You don't want to be updating your objects in Elasticsearch always while running tests. You want to do it only when you'll be explicitly testing your search functionality (or indexing/deleting from index). To do so, you will have to disable searchkick callbacks, define a custom tag for your tests and enable indexing only for these tests. You may have to handle cleaning your index after a test/groups of tests as well.

    @vich's point is also important, you currently create your object too late, after the request.

    I would change your setup to:

    context 'GET #index', :search do
      let!(:house) { create(:house) }
      before { get :index }
    
      it 'assigns @houses' do
        expect(assigns(:houses).results).to eq([house])
      end
    end