Rspec功能测试与sidekiq邮件传递,如何等待邮件观察者?



当我通过deliver_later发送邮件时,它由sidekiq管理,然后我的注册邮件观察器被触发。

我有一个 Capybara 测试,可以检查观察器代码中更改的状态,但如果观察器在单击后没有立即执行,并且期望无法正常工作,它会随机失败。

例:

# spec
scenario 'Test that fails randomly' do
click_link "Go!"
# MyModel#done is a boolean attribute, so we have #done? method availiable
expect(MyModel.first.done?).to be true
end
# The controller that manages the Go! link, triggers a mailer.
# After the mailer, this is executed.
# Registered observer
def delivered_mail(mail)
email = Email.find_by_message_id mail.message_id
email.user.update_attributes done: true
end

有趣的事实:如果我隔离执行此场景,测试将始终通过。 如果我完全执行测试套件,测试将 9:1 失败:或多或少通过。̄_(ツ(_/̄

尝试将其放入rails_helper:

require 'sidekiq/testing'
RSpec.configure do |config|
Sidekiq::Testing.inline!
end

并且还将Sidekiq::Testing.inline!放在scenario块的第一行......无。同样有趣的事实。

更新:

添加了database_cleanergem,现在每次都失败。

水豚中的动作(click_link等(对它们触发的任何行为一无所知。 因此,无法保证在您的click_link行返回后应用程序将执行什么操作,除了单击链接,并且浏览器将开始执行该操作触发的任何操作。 然后,您的测试会立即检查"MyModel.first.done?",而浏览器仍可能提交请求(这就是为什么在功能测试中直接检查数据库记录通常不受欢迎的原因之一(。

解决方案(并最终得到可以可靠地跨多个驱动程序工作的测试(是检查页面上指示操作已完成的视觉更改。 您还需要正确设置 ActiveJob 进行测试,以便确保执行作业。 为此,您需要include ActiveJob::TestHelper,这可以在您的 RSpec 配置或单个场景中完成,并且您需要确保设置ActiveJob::Base.queue_adapter = :test(如果需要,可以在 config/environment/tests.rb 文件中完成(。 然后,假设您的应用程序在操作完成后在屏幕上显示一条消息"邮件已发送!

include ActiveJob::TestHelper 
ActiveJob::Base.queue_adapater = :test
...
perform_enqueued_jobs do
click_link "Go!"
expect(page).to have_text('Mail sent!') # This will wait for the message to appear, which guarantees the action has completed and enqueued the job
end # when this returns any jobs enqueued during the block will have been executed
expect(MyModel.first.done?).to be true

最新更新