Rails 6和deliver_later不影响ActionMailer::Base.deliveries

13
升级到Rails 6后,我注意到默认邮件程序的.deliver_later与Rails 5中的不同。
配置:
config.active_job.queue_adapter = :inline
当运行Mailer.register_email(...).deliver_later时,在ActionMailer::Base.deliveries中没有存储任何内容。只有在运行perform_enqueued_jobs时,该数组才会被填充-似乎queue_adapter = :inline不按照我的预期工作。
如果我运行Mailer.send(...).deliver_now,那么ActionMailer::Base.deliveries中就会有适当的值。
为什么会出现这种情况以及如何解决?您有什么想法吗?

2
这种行为在Rails 5和Rails 6之间发生了变化。我找不到具体的位置,但我看到Rails现在在他们的Minitest电子邮件助手中调用perform_enqueued_jobs。他们添加了一个过滤器,以确保只有电子邮件作业是以这种方式执行的。 https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/test_helper.rb#L37 - DylanReile
3个回答

6

我在我的测试中也遇到了同样的问题。在互联网上搜索后没有找到答案,所以我开始进行试验。

我尝试将发送邮件的调用方法包装在

assert_emails 1 do
  Mailer.register_email(...).deliver_later
end

在那之后,ActionMailer::Base.deliveries 正确地填充。


2

问题

问题出在 Rails 6 中新增的两行代码(第一行第二行), 基本上,回调函数before_setup在这里被定义(在 RSpec 中 这里,在 Minitest 中 这里),被覆盖了(通过这个),因此强制队列适配器成为测试适配器,而不是由config.active_job.queue_adapter定义的那个。

解决方法

因此,为了使用由config.active_job.queue_adapter定义的queue_adapter,并恢复Rails 5的行为,我们可以像下面这样做。

# spec/support/active_job/test_helper.rb
module ActiveJob
  module TestHelper
    def before_setup
      super
    end
  end
end

谢谢你,@andres-leon!你为我节省了很多时间来调试这个问题!非常好的回答! - DjezzzL

0
如果电子邮件的确切数量可能会轻松更改,这是另一个选项:
assert_changes 'enqueued_jobs.size' do
  # Some code that sends email with deliver_later
end

这允许您测试电子邮件是否已发送,但它忽略了确切的数量(这是asserts_emails方法的限制 - 除此之外,asserts_emails方法非常好用)。 我发现enqueued_jobs方法在测试任何后台作业时都非常有帮助,包括deliver_later

注意:上面的示例仅检查排队的作业列表是否已更改。如果您想更具体地检查队列是否已更改为电子邮件,请执行以下操作:

assert_changes 'enqueued_jobs.select {|job| job["job_class"] == "ActionMailer::MailDeliveryJob"}.size' do
  # Some code that sends email with deliver_later
end


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