使用 Rspec + Factory Girl 在新线程/进程测试中数据库为空

Database empty in new Thread / Process testing with Rspec + Factory Girl

关注此博客 post、http://blog.arkency.com/2015/09/testing-race-conditions/

我正在尝试测试并发性。但是在我的规范中,当我启动一个新线程或 fork 一个进程时,我无法找到记录。

describe 'test concurrency' do
  let(:order_1) { create(:order) }
  let(:order_2) { create(:order) }
  let(:order_3) { create(:order) }
  let(:order_4) { create(:order) }
  let(:product) { create(:product) }

  it 'test concurrency' do
    wait_for_all_threads = true
    product.update(quantity_available: 4, quantity_sold: 0, quantity_in_carts: 0)
    orders = [order_1, order_2, order_3, order_4]

    # Objects are persisted in here
    # because order_n.persisted => true
    # product.persisted => true
    # product.reload works without issue (and this is essentially what causes the RecordNotFound error in Order#add_item)

    threads = orders.map do |order|
      Thread.new do

        # Objects cannot be found in the database

        true while wait_for_all_threads

        item = order.add_item(product, 1)
        order_items << item
      end
    end

    wait_for_all_threads = false

    threads.each(&:join)

    # ...
    # here comes all the expects ...
    # not gonna post it because it's not what matters in this question
  end
end

经过研究,我设置了这些:

DatabaseCleaner.strategy = :truncation
config.use_transactional_fixtures = false

但运气不好。

所以问题是,在新线程中,none 个创建的对象可以在数据库中找到。

我正在挖掘的一些线索:

使用 Rails 5 这对我有用。描述中的位置:

self.use_transactional_tests = false

"use_transactional_fixtures" 已弃用。

我还必须通过以下方式绕过 DatabaseCleaner:

it 'tests concurrency', bypass_cleaner: true do

end

然后在 rails_helper(或者你有 DatabaseCleaner 设置的地方)

config.around(:each) do |example|
  if example.metadata[:bypass_cleaner]
    example.run
  else
    # database cleaner code
  end
end

希望这对您或其他人有所帮助:)