gpt4 book ai didi

ruby-on-rails - 如何在 Rails 测试中用 proc 和 yield 覆盖类?

转载 作者:行者123 更新时间:2023-11-28 20:54:08 25 4
gpt4 key购买 nike

我有以下类(class)(仅作为示例),

class Background
def self.add_thread(&blcok)
Thread.new do
yield
ActiveRecord::Base.connection.close
end
end
end

class Email
def send_email_in_other_thread
Background.add_thread do
send_email
end
end
def send_email
UserMailer.greeting_email.deliver_now
end
end

下面的代码用于测试,

class EmailTest < ActiveSupport::TestCase
class Background
def self.add_thread(&block)
yield
end
end

test 'should send email' do
assert_difference 'ActionMailer::Base.deliveries.size', 1 do
send_email_in_other_thread
end
end
end

但是这个测试失败了,“ActionMailer::Base.deliveries.size”并没有改变 1。大约 20 次中有 1 次成功。
我认为这是因为修改了 Background 类。也许在测试中重写不起作用或者 yield proc 不是立即执行而是延迟执行。
我尝试使用“block.call”而不是 yield,但结果是一样的。
我怎样才能让这个测试总是成功?

最佳答案

这看起来像是一个经典的竞争条件。 Thread.new 在线程生成后立即返回,而不是在它的工作完成时返回。

因为您的主线程不会停止执行,所以大多数时候您的断言会在邮件发送之前运行。

您可以使用 join方法等待发送线程在返回之前完成执行,但随后它本质上又等同于单个线程,因为它会阻塞调用(主)线程直到工作完成。

Thread.new do
yield
ActiveRecord::Base.connection.close
end.join

然而,在 Rails 中处理后台作业方面已经有一些很棒的东西了。查看SideKiqResque例如。

关于ruby-on-rails - 如何在 Rails 测试中用 proc 和 yield 覆盖类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32677966/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com