【问题标题】:How can I write RSpec tests that make sure records are being reindexed by Searchkick?如何编写 RSpec 测试以确保 Searchkick 正在重新索引记录?
【发布时间】: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


【解决方案1】:

我想确保我在 Image 上的 after_create 挂钩导致 Product 被重新索引。

您不是在测试重新索引,只是在适当的时间启动重新索引。所以模拟是要走的路。如果您认为有必要,请在其他地方测试实际的重新索引。

假设图像看起来像这样:

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,您将检查是否有一个重新索引作业已排队。

【讨论】:

  • 这正是我需要听到的。谢谢施韦恩!
猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 2019-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多