在与Rspec示例并行实现Resque时,我感到很困惑。
以下是一个昂贵的方法.generate(self)
的类
class SomeClass
...
ChangeGenerator.generate(个体经营)
...
端
实现resque后,上面的类更改为以下内容并添加了ChangeRecorderJob类。
class SomeClass
...
Resque.enqueue(ChangeRecorderJob, self.id)
...
end
class ChangeRecorderJob
@queue = :change_recorder_job
def self.perform(noti_id)
notification = Notification.find(noti_id)
ChangeGenerator.generate(notification)
end
end
完美无缺。但我有两个问题。
之前,我的示例规范用于测试整个.generate(self)
方法的堆栈。但是现在我把它推进到Resque工作中,我如何能够将我的示例连接起来以使相同的测试变为绿色而不会孤立?或者我必须隔离测试??
最后,如果我有10个工作岗位,我是否必须使用self.perform
方法创建10个单独的工作类?
答案 0 :(得分:33)
测试这样的异步内容总是很棘手。我们所做的是:
在我们的功能测试中,我们确保作业入队。使用mocha或类似的东西通常就足够了。如果要运行测试redis服务器,可以验证正确的队列是否增长以及作业参数是否正确。虽然你现在正在测试Resque本身。
作为单元测试,单独测试作业。由于它们只有一个名为perform
的类方法,因此您的单元测试非常简单。在您的情况下,您将测试ChangeRecorderJob.perform执行您想要的操作。我们倾向于测试工作是否在适当的队列中,工作的参数是否有效,以及工作是否符合我们的要求。
现在,一起测试一切是棘手的部分。我已经完成了两种不同的方式,每种方式都有利有弊:
Resque.inline = true
而不是猴子修补 同步运行作业到目前为止更容易。您只需在spec_helper中加载类似以下内容:
module Resque alias_method :enqueue_async, :enqueue def self.enqueue(klass, *args) klass.new(0, *args).perform end end击>
<击> 撞击>
从resque 1.14.0开始,你可以在初始化程序中设置Resque.inline = true
而不是猴子修补程序。如果你坚持使用较旧版本的resque,那么猴子补丁是必要的。
请注意,因为您在这里同步运行,所以您将承担长期工作的成本。也许更重要的是,你将在同一个过程中运行,因此它不能完全准确地表示你的工作将如何运行。
要在分叉工作程序中运行该作业,就像resque一样,您需要执行以下操作:
def run_resque_job(job_class, job_args, opts={}) queue = opts[:queue] || "test_queue" Resque::Job.create(queue, job_class, *job_args) worker = Resque::Worker.new(queue) worker.very_verbose = true if opts[:verbose] if opts[:fork] # do a single job then shutdown def worker.done_working super shutdown end worker.work(0.01) else job = worker.reserve worker.perform(job) end end
让工作人员从队列中弹出作业有一点延迟。当然,您需要运行一个测试redis服务器,以便工作人员可以弹出一个队列。
我确信其他人已经提出了测试resque工作的聪明方法。这些都是为我工作的。
答案 1 :(得分:8)
使用resque_spec进行单元测试。
describe "#recalculate" do
before do
ResqueSpec.reset!
end
it "adds person.calculate to the Person queue" do
person.recalculate
Person.should have_queued(person.id, :calculate).in(:people)
end
end
对于您的集成测试:
describe "#score!" do
before do
ResqueSpec.reset!
end
it "increases the score" do
with_resque do
game.score!
end
game.score.should == 10
end
end
答案 2 :(得分:1)
您必须进行两项不同的测试。一个用于验证,以确保将作业排入Resque队列,第二个用于确保工作人员接收的队列中的作业正在满足您的要求。
不,你不需要编写10种不同的执行方法。当你运行Resque worker时,他们从队列中获取作业并盲目地调用你工作的.perform方法。所以,你的工作应该有执行方法。