我如何编写 RSpec 测试来确保记录被 Searchkick 重新索引?
How can I write RSpec tests that make sure records are being reindexed by Searchkick?
问题
我正在编写一个规范来测试当我创建关联的图像记录时我的产品模型是否得到重新索引。
文档建议在测试中调用 Product.search_index.refresh
以确保索引是最新的,但这违背了目的,因为我想确保图像上的 after_create 挂钩导致要重新编制索引的产品。
解决方案 1:在我的测试中使用 sleep
我可以调用 sleep
等待 Searchkick 更新索引,但这会减慢我的测试速度并使它们变得脆弱。
product = create(:product)
Product.search_index.refresh
image_name = 'a_lovely_book.png'
search_results = Product.search image_name, fields: [:image_names]
# This passes.
expect(search_results.count).to eq(0)
image = create(:product_image, name: image_name)
# This causes the test to pass because it gives Searchkick time to reindex Product.
sleep 5
# This succeeds if I have the sleep call above.
search_results = Product.search image_name, fields: [:image_names]
expect(search_results.count).to eq(1)
解决方案 2:如果 Rails.env.test?
立即更新索引
我也考虑过在我的图像 class 中做类似的事情,以便在测试中立即重新索引。但我希望编写大量此类测试,并且我不想一遍又一遍地重复这段代码。
class Image
belongs_to :product
after_create :reindex_product
def reindex_product
if Rails.env.test?
product.search_index.refresh
else
product.reindex
end
end
end
解决方案 3:使用间谍或模拟
不确定我该怎么做,但也许有一种方法可以使用间谍或模拟来确保 reindex
方法在 Product 上被调用?
I want to make sure that my after_create hooks on Image are causing Product to get reindexed.
您不是在测试重新索引,只是在适当的时间启动了重新索引。所以模拟是要走的路。如果您觉得有必要,请在别处测试实际的重建索引。
假设图像看起来像这样:
class Image < ApplicationRecord
belongs_to :product
# Note: the docs suggest after_commit so all saves will be reindexed.
after_commit :reindex_product
def reindex_product
product.reindex
end
end
RSpec 中的测试看起来像...
describe '.create' do
it 'reindexes the product' do
expect(product).to receive(:reindex)
Image.create( product: product, ... )
end
end
# This test illustrates why after_create might be insufficient.
describe '#save' do
it 'reindexes the product' do
expect(product).to receive(:reindex)
image = Image.new( product: product, ... )
image.save!
end
end
或者,如果您正在使用 asynchronous reindexing,您将检查重建索引作业是否已排队。
问题
我正在编写一个规范来测试当我创建关联的图像记录时我的产品模型是否得到重新索引。
文档建议在测试中调用 Product.search_index.refresh
以确保索引是最新的,但这违背了目的,因为我想确保图像上的 after_create 挂钩导致要重新编制索引的产品。
解决方案 1:在我的测试中使用 sleep
我可以调用 sleep
等待 Searchkick 更新索引,但这会减慢我的测试速度并使它们变得脆弱。
product = create(:product)
Product.search_index.refresh
image_name = 'a_lovely_book.png'
search_results = Product.search image_name, fields: [:image_names]
# This passes.
expect(search_results.count).to eq(0)
image = create(:product_image, name: image_name)
# This causes the test to pass because it gives Searchkick time to reindex Product.
sleep 5
# This succeeds if I have the sleep call above.
search_results = Product.search image_name, fields: [:image_names]
expect(search_results.count).to eq(1)
解决方案 2:如果 Rails.env.test?
立即更新索引我也考虑过在我的图像 class 中做类似的事情,以便在测试中立即重新索引。但我希望编写大量此类测试,并且我不想一遍又一遍地重复这段代码。
class Image
belongs_to :product
after_create :reindex_product
def reindex_product
if Rails.env.test?
product.search_index.refresh
else
product.reindex
end
end
end
解决方案 3:使用间谍或模拟
不确定我该怎么做,但也许有一种方法可以使用间谍或模拟来确保 reindex
方法在 Product 上被调用?
I want to make sure that my after_create hooks on Image are causing Product to get reindexed.
您不是在测试重新索引,只是在适当的时间启动了重新索引。所以模拟是要走的路。如果您觉得有必要,请在别处测试实际的重建索引。
假设图像看起来像这样:
class Image < ApplicationRecord
belongs_to :product
# Note: the docs suggest after_commit so all saves will be reindexed.
after_commit :reindex_product
def reindex_product
product.reindex
end
end
RSpec 中的测试看起来像...
describe '.create' do
it 'reindexes the product' do
expect(product).to receive(:reindex)
Image.create( product: product, ... )
end
end
# This test illustrates why after_create might be insufficient.
describe '#save' do
it 'reindexes the product' do
expect(product).to receive(:reindex)
image = Image.new( product: product, ... )
image.save!
end
end
或者,如果您正在使用 asynchronous reindexing,您将检查重建索引作业是否已排队。