使用RSpec和mocking测试after_commit

Mih*_*kov 29 ruby rspec ruby-on-rails mocking

我有一个模型负责人和一个回调: after_commit :create, :send_to_SPL

我使用的是Rails-4.1.0,ruby-2.1.1,RSpec.

1)此规范未通过:

context 'callbacks' do
  it 'shall call \'send_to_SPL\' after create' do
    expect(lead).to receive(:send_to_SPL)
    lead = Lead.create(init_hash)
    p lead.new_record? # => false
  end
end
Run Code Online (Sandbox Code Playgroud)

2)这个规范也没有通过:

context 'callbacks' do
  it 'shall call \'send_to_SPL\' after create' do
    expect(ActiveSupport::Callbacks::Callback).to receive(:build)
    lead = Lead.create(init_hash)
  end
end
Run Code Online (Sandbox Code Playgroud)

3)这个是通过,但我认为它不是测试after_commit回调:

context 'callbacks' do
  it 'shall call \'send_to_SPL\' after create' do
    expect(lead).to receive(:send_to_SPL)
    lead.send(:send_to_SPL)
  end
end
Run Code Online (Sandbox Code Playgroud)

在Rails中测试after_commit回调的最佳方法是什么?

iha*_*dez 47

我认为Mihail Davydenkov的评论应该是一个答案:

你也可以使用subject.run_callbacks(:commit).

另请注意,此问题(在事务测试中未调用提交回调)应在rails 5.0+中修复,因此您可能希望在升级时删除可能在此期间使用的任何变通方法.请参阅:https://github.com/rails/rails/pull/18458


Ole*_*dul 39

尝试使用test_after_commit gem

或者在spec/support/helpers/test_after_commit.rb中添加以下代码 - Gist

  • You also can use `subject.run_callbacks(:commit)` in the end of the body of the block `it` (34认同)
  • 这个 gem 非常适合 Rails 3 和 Rails 4。在 Rails 5 中,它不再需要,因为它已添加到核心:https://github.com/rails/rails/pull/18458/commits/eb72e349b205c47a64faa5d6fe9f831aa7fdddf3 (2认同)

Koe*_*en. 6

我正在使用DatabaseCleaner,配置我可以在事务和截断之间轻松切换,前者是首选,因为速度,但后者可用于测试回调.

RSpec beforeafter处理程序使用范围,因此如果要将截断作为范围,请定义before处理程序;

config.before(:each, truncate: true) do
  DatabaseCleaner.strategy = :truncation
end
Run Code Online (Sandbox Code Playgroud)

而现在使用此配置的describe,contextit块,你应该声明它想:

describe "callbacks", truncate: true do
   # all specs within this block will be using the truncation strategy
  describe "#save" do
    it "should trigger my callback" do
      expect(lead).to receive(:send_to_SPL)
      lead = Lead.create(init_hash)
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

完整挂钩配置:(存储spec/support/database_cleaner.rb)

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, truncate: true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.append_after(:each) do
    DatabaseCleaner.clean
  end
end
Run Code Online (Sandbox Code Playgroud)