如何在rails的测试中使用proc和yield覆盖类? [英] How can I overriding class with proc and yield in test on rails?
问题描述
我有以下课程(仅作为示例),
I have below classes(only for example),
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 yield进程,但会延迟执行.
我尝试使用"block.call"而不是yield,但是结果是相同的.
我怎样才能使测试始终成功?
But this test fails, "ActionMailer::Base.deliveries.size" didn't change by 1.
And 1 in about 20 times success.
I think it is because of the modified Background class. Maybe overriding in test doesn't work or yield proc is not executed instantly but in delayed.
I tried 'block.call' instead of yield, but the result is same.
How can I make this test always be success?
推荐答案
这看起来像是经典的比赛条件. Thread.new
在线程产生后立即返回,而不是在工作完成时返回.
This looks like a classic race condition. Thread.new
returns as soon as the thread is spawned, not when it's work is completed.
由于主线程不会停止执行,因此大多数情况下,断言是在邮件发送之前运行的.
Because your main thread doesn't halt execution, most of the time your assertion is run before the mail has been sent.
您可以使用 join 方法在返回之前等待发送线程完成执行,但是从本质上讲,它将再次等效于单个线程,因为它阻塞了调用(主)线程,直到工作完成.
You could use the join method to wait for the sending thread to finish execution before returning, but then it would essentially be equivalent to a single thread again, as it blocks the calling (main) thread until work is done.
Thread.new do
yield
ActiveRecord::Base.connection.close
end.join
但是,在Rails中已经有一些很棒的宝石可以用来处理后台作业.查看 SideKiq 和要求.
There are already some great gems, however, for dealing with background jobs in Rails. Check out SideKiq and Resque for example.
这篇关于如何在rails的测试中使用proc和yield覆盖类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!