使用ActiveJob在rspec中执行待处理的任务

28

我有这段代码用于使用Rspec测试ActiveJob和ActionMailer,但我不知道如何真正执行所有排队的作业。

describe 'whatever' do
  include ActiveJob::TestHelper

  after do
    clear_enqueued_jobs
  end  

  it 'should email' do
    expect(enqueued_jobs.size).to eq(1)
  end
end

也许这会有所帮助 https://medium.com/@chuckjhardy/testing-rails-activejob-with-rspec-5c3de1a64b66 - ChuckJHardy
4个回答

29

正确的测试方法是检查排队的任务数量,就像您的示例中一样,然后逐个测试每个任务。如果您想进行整合测试,可以尝试使用perform_enqueued_jobs助手:

正确的测试方法是像您的示例那样检查已入队的作业数量,然后逐个测试每个作业。如果您想进行集成测试,可以尝试使用perform_enqueued_jobs助手:

describe 'whatever' do
  include ActiveJob::TestHelper

  after do
    clear_enqueued_jobs
  end  

  it 'should email' do
    perform_enqueued_jobs do
      SomeClass.some_action
    end
  end
end

请参阅ActiveJob::TestHelper文档


3
有人可以展示一个更为自然的例子,演示如何使用接受参数的邮件发送器吗?我好像无法使用类似 OrderMailer.receipt_email(order.id) 这样的语法实现。 - Chris Peters
在测试邮件发送器并尝试触发作业时,请确保附加deliver_now或deliver_later方法。 - David Melin

26

以下是我解决类似问题的方法:

# rails_helper.rb
RSpec.configure do |config|
  config.before :example, perform_enqueued: true do
    @old_perform_enqueued_jobs = ActiveJob::Base.queue_adapter.perform_enqueued_jobs
    @old_perform_enqueued_at_jobs = ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs
    ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
    ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
  end

  config.after :example, perform_enqueued: true do
    ActiveJob::Base.queue_adapter.perform_enqueued_jobs = @old_perform_enqueued_jobs
    ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = @old_perform_enqueued_at_jobs
  end
end

那么在规格中,我们可以使用:

it "should perform immediately", perform_enqueued: true do
  SomeJob.perform_later  
end

很好的答案。我将其添加到spec/support文件中。在集成测试中测试电子邮件值似乎是必须的,这一点非常重要。 - justingordon
这真的是确保特定集成测试中作业以内联方式执行的唯一方法吗?让我感到惊讶的是,居然没有更简单的方法来做到这一点。 - cgat
1
@cgat 不需要- 你可以将"ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true"放在before块中,这样你的被enqueued的job就会在你的测试用例运行前执行。 - colemerrick

1

我有一个:inline_jobs助手,当应用于测试时,它将执行排队的作业并清除排队的作业

module InlineJobHelpers
  def self.included(example_group)
    example_group.around(:each, :inline_jobs) do |example|
      perform_enqueued_jobs do
        example.run
      end
    ensure
      clear_enqueued_jobs
    end
  end
end

RSpec.configure do |config|
  config.include ActiveJob::TestHelper, :inline_jobs
  config.include InlineJobHelpers, :inline_jobs
end

0

将所有最好的部分组合在一起,+包括sidekiq:

spec/support/perform_jobs.rb:

require 'sidekiq/testing'

RSpec.configure do |config|
  Sidekiq::Testing.fake!

  config.around(:each, perform_jobs: true) do |example|
    Sidekiq::Testing.inline! do
      queue_adapter = ActiveJob::Base.queue_adapter
      old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs
      old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs
      queue_adapter.perform_enqueued_jobs = true
      queue_adapter.perform_enqueued_at_jobs = true
      example.run
    ensure
      queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
      queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
    end
  end

end

spec/some_spec.rb:

it 'works', perform_jobs: true do
  ...
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接