升级至Rails 6后ActionMailer测试失败问题求助
嘿,我来帮你搞定这个Rails升级后的邮件测试问题!你遇到的情况其实是Rails 6对邮件投递机制做了默认变更,再加上你配置的:classic自动加载器,才导致测试里的邮件没被正确统计到ActionMailer::Base.deliveries数组中。下面是具体的解决步骤:
1. 在测试中强制执行异步邮件任务
Rails 6默认使用ActionMailer::MailDeliveryJob(替代旧版的ActionMailer::DeliveryJob)来异步投递邮件,而测试环境默认不会自动执行队列中的任务,所以邮件不会立刻出现在deliveries里。你可以用perform_enqueued_jobs包裹触发邮件的操作,强制任务执行:
test "send email" do VCR.use_cassette('mailgun api key') do ActionMailer::Base.deliveries.clear item = items(:saved) # 包裹触发邮件的操作,强制执行队列中的投递任务 perform_enqueued_jobs do visit item_path(item) click_button "Send" end assert_equal 1, ActionMailer::Base.deliveries.count end end
如果想让所有测试都自动执行队列任务,也可以在test/test_helper.rb的测试基类里全局配置:
class ActiveSupport::TestCase # ... 保留原有配置 setup do # 确保邮件投递功能处于开启状态 ActionMailer::Base.perform_deliveries = true # 自动执行所有入队的异步任务 perform_enqueued_jobs end end
2. 确保:classic自动加载器能正确加载邮件Job
因为你设置了config.autoloader = :classic,需要确认ActionMailer::MailDeliveryJob能被正确加载。默认情况下app/mailers目录已经在自动加载路径中,但可以手动在config/application.rb里明确声明,避免加载问题:
config.autoloader = :classic # 确保邮件相关目录被包含在自动加载路径内 config.autoload_paths << Rails.root.join('app/mailers')
3. 核对测试环境的邮件配置
最后检查一下config/environments/test.rb里的邮件配置,确保是测试模式(默认应该是正确的,但升级后可以再确认):
config.action_mailer.delivery_method = :test config.action_mailer.perform_deliveries = true
问题根源说明
Rails 6把邮件投递的默认行为从同步的deliver_now改成了异步的deliver_later,对应的Job类也换成了ActionMailer::MailDeliveryJob。在测试环境中,异步任务不会自动执行,所以邮件不会被投递到deliveries数组,导致你看到的Expected: 1 Actual: 0断言失败。另外:classic自动加载器如果没有正确包含邮件目录,可能会导致Job无法被加载,进一步触发这个问题。
内容的提问来源于stack exchange,提问作者RomanOks

