为啥在请求测试中不使用 ActiveJob InlineAdapter?

Posted

技术标签:

【中文标题】为啥在请求测试中不使用 ActiveJob InlineAdapter?【英文标题】:Why is ActiveJob InlineAdapter not used in request tests?为什么在请求测试中不使用 ActiveJob InlineAdapter? 【发布时间】:2021-12-19 15:48:01 【问题描述】:

我的 test.rb 中有这段代码:

config.active_job.queue_adapter = :inline

在测试中我有:

scenario '15 minutes after last call a recall should happen' do    
  p ActiveJob::Base.queue_adapter
end

这会返回: ActiveJob::QueueAdapters::InlineAdapter

这很好,因为 perform_later 会立即执行。

但是,当我像这样将 type: :request 添加到测试中时:

scenario '15 minutes after last call a recall should happen', type: :request do    
  p ActiveJob::Base.queue_adapter
end

我得到:requestActiveJob::QueueAdapters::TestAdapter 并且 perform_later 不再执行。这是预期的行为吗?如何确保 perform_later 块始终在测试中执行?

【问题讨论】:

【参考方案1】:

作业不会排队执行,但会排队检查是否已排队(basically just saved in an array,因此您可以测试它们是否存在):

https://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters/TestAdapter.html

既然你用 rspec 标记了这个问题,那么你就有了完美的匹配器:have_been_enqueued,可以这样使用:

RSpec.describe UploadBackupsJob do
  it "matches with enqueued job" do
    ActiveJob::Base.queue_adapter = :test
    UploadBackupsJob.perform_later
    expect(UploadBackupsJob).to have_been_enqueued
  end
end

【讨论】:

如何确保 perform_later 块始终在测试中执行?当不包括类型请求时,它们被执行。即使我指定了我想要内联适配器,为什么它使用不同的队列适配器?【参考方案2】:

这和这个问题有关:https://github.com/rails/rails/issues/37270

投入

(ActiveJob::Base.descendants << ActiveJob::Base).each(&:disable_test_adapter)

在实际测试中修复它。

另一个更简洁的选择是(如果可能)将测试类型更改为:type: :system 并确保您的 rspec-rails 版本 >= 4.1

【讨论】:

以上是关于为啥在请求测试中不使用 ActiveJob InlineAdapter?的主要内容,如果未能解决你的问题,请参考以下文章

集成测试ActionMailer和ActiveJob

rspec rails testing:如何强制 ActiveJob 作业内联运行某些测试?

为啥请求中不包含授权标头? - 认证0

为啥请求 http 在 Kotlin 中不起作用?

在 rspec 中使用 ActiveJob 执行挂起的作业

在 Rails 中安排一个 ActiveJob