Ruby on rails 使用sidekiq邮件传递进行Rspec功能测试,如何等待邮件观察者?

Ruby on rails 使用sidekiq邮件传递进行Rspec功能测试,如何等待邮件观察者?,ruby-on-rails,rspec,capybara,sidekiq,Ruby On Rails,Rspec,Capybara,Sidekiq,当我通过deliver\u later发送邮件时,它由sidekiq管理,然后我的注册邮件观察员被触发 我有一个Capybara测试,它检查观察者代码中更改的状态,但是如果在单击之后没有立即执行观察者,并且期望值不能正确工作,它就会随机失败 例如: # spec scenario 'Test that fails randomly' do click_link "Go!" # MyModel#done is a boolean attribute, so we hav

当我通过
deliver\u 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\u帮助程序:

require 'sidekiq/testing'
RSpec.configure do |config|
  Sidekiq::Testing.inline!
end
同时也把
Sidekiq::Testing.inline!
放在
场景
的第一行,什么都不做。同样有趣的事实

更新: 添加了
database\u cleaner
gem,现在每次都会失败。

在Capybara中执行操作(
单击链接
,等等)对它们触发的任何行为一无所知。因此,除了单击链接外,无法保证在您的
单击链接返回后应用程序会执行什么操作,浏览器会开始执行该操作触发的任何操作。然后,您的测试会立即检查“MyModel.first.done?”wh浏览器可能仍在提交请求(这是不赞成在功能测试中直接检查数据库记录的原因之一)

解决办法是什么(最终的测试将在多个驱动程序之间可靠地工作,即检查页面上指示操作已完成的视觉更改。您还需要正确设置ActiveJob进行测试,以便确保作业已执行。为此,您需要
包括ActiveJob::TestHelper
,这可以在您的RSpec配置或单个场景,并且您需要确保设置了
ActiveJob::Base.queue_adapter=:test
(如果需要,可以在config/environment/tests.rb文件中完成)。然后假设您的应用程序在操作完成后在屏幕上显示消息“Mail sent!”,您可以这样做

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
水豚行动(点击链接等)对它们触发的任何行为一无所知。因此,除了单击链接外,无法保证在您的
单击链接返回后应用程序会执行什么操作,浏览器会开始执行该操作触发的任何操作。然后,您的测试会立即检查“MyModel.first.done?”wh浏览器可能仍在提交请求(这是不赞成在功能测试中直接检查数据库记录的原因之一)

解决办法是什么(最终的测试将在多个驱动程序之间可靠地工作,即检查页面上指示操作已完成的视觉更改。您还需要正确设置ActiveJob进行测试,以便确保作业已执行。为此,您需要
包括ActiveJob::TestHelper
,这可以在您的RSpec配置或单个场景,并且您需要确保设置了
ActiveJob::Base.queue_adapter=:test
(如果需要,可以在config/environment/tests.rb文件中完成)。然后假设您的应用程序在操作完成后在屏幕上显示消息“Mail sent!”,您可以这样做

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

我以前也想过(事实上尝试过),但不起作用。页面在
MyModel.first.done之前一直有“Mail sent!”,因为属性更新是在Observer类中完成的,在发送电子邮件后立即触发(这可能发生在页面显示后,因为电子邮件只排队)@PedroAdameVergara使用您可能希望查看的体系结构,包括
ActiveJob::TestHelper
,设置
ActiveJob::Base.queue\u adapter=:test
,然后在
执行排队的\u作业
中在您的最终期望之前包装测试,这样您就可以保证在期望之前执行作业ns-你仍然需要
have_text
,因为这样一来就保证了工作已经排好了队。你没有意识到我有多爱你。我不敢相信它在一整天后终于起作用了。谢谢!这就成功了,尽管我不需要
have_text
请将它作为答复添加进来,我会接受它。@PedroAdameVergara up注明答案日期-我建议保留
have_text
这将防止出现片状,特别是如果你想换一个不同的驱动程序。我以前想过(事实上尝试过),但不起作用。页面在
MyModel.first.done?
之前一直有“Mail sent!”,这是因为属性更新是在Observer类中完成的,该类在发送电子邮件后立即触发(这可能发生在页面显示后,因为电子邮件仅排队)@PedroAdameVergara使用您可能希望查看的体系结构,包括
ActiveJob::TestHelper
,设置
ActiveJob::Base.queue\u adapter=:test
,然后在
执行排队的\u作业
中在您的最终期望之前包装测试,这样您就可以保证在期望之前执行作业ns-你仍然需要
have_text
,因为这样一来就保证了工作已经排好了队。你没有意识到我有多爱你。我不敢相信它在一整天后终于起作用了。谢谢!这就成功了,尽管我不需要
have_text
请将它作为答复添加进来,我会接受它。@PedroAdameVergara up注明答案日期-我建议保留
have_text
,这将防止出现片状,特别是如果您想换到其他驱动程序。