【发布时间】:2020-09-16 17:44:29
【问题描述】:
问题
我正在编写一个规范来测试当我创建关联的图像记录时我的产品模型是否被重新索引。
文档建议在测试中调用 Product.search_index.refresh 以确保索引是最新的,但这违背了目的,因为我想确保 Image 上的 after_create 挂钩导致 Product 被重新索引。
解决方案 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)
方案二:如果 Rails.env.test 立即更新索引?
我还考虑在我的 Image 类中做这样的事情,以便在测试中立即进行重新索引。但我希望编写大量此类测试,并且我不想一遍又一遍地重复此代码。
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:使用间谍或模拟
不确定我该如何准确地做到这一点,但也许有一种方法可以使用间谍或模拟来确保在 Product 上调用 reindex 方法?
【问题讨论】:
-
在幕后,用于更新索引的逻辑是相同的,只是异步执行,所以如果它同步工作,那么假设它会异步工作是安全的。尝试测试异步组件是否工作会进入“我正在测试别人的代码”领域。如果您必须测试异步部分,请尝试创建一个对象然后
loop do; <query searchkick index for newly created record>; found_record? ? break : sleep 1; end等待它更新。 -
解决方案 3 是正确的。模拟重新索引的调用并确保它被调用。除此之外,您还进入了测试 3rd 方代码的领域,这是一个很大的禁忌。
-
请给我们看看
Image的相关部分好吗?
标签: ruby-on-rails ruby rspec searchkick