3

我想测试一些 resque 工人,以及与这些工人一起排队工作的行为。我正在使用 rspec 和 rails。

目前我有一个模型,我们称之为 Article.rb,它有一个名为 updates_related_categories 的 before_save 方法,用于检查是否需要将具有 CategoriesSorter 的作业加入队列。如果是这样,它会使用与该文章相关的类别 id 的参数将该工作排入队列。

然而,在测试中,这些作业被发送到与开发服务器发送作业相同的队列中。(我使用 resque 服务器进行检查,您可以在 root/redis/overview 中绑定到您的服务器)

我想知道:

1) 如何将测试作业发送到与开发作业不同的队列?

如果这是可能的,也欢迎任何其他关于测试 resque 的建议。

我已经看到一些相关的问题,建议使用 resque-unit 和 resque-spec,但这些问题还很不成熟,我无法让它们进入有用的工作状态。另外,我听说过使用 Resque.inline 但我不知道这在这种情况下是否相关,因为在测试规范中没有调用 resque,它是在保存测试中创建的对象的文章模型中调用的。

示例代码:

文章.rb:

 before_save :update_related_categories
 def update_related_categories
     #some if statements/checks to see if a related category needs updating
         Resque.enqueue(CategoriesWorker, [category_id])
     end
 end

分类排序器:

 class CategoriesSorter
     @queue=:sorting_queue
     def self.perform(ids)
        ids.each do |id|
           #some code
        end
      end
 end

眼镜:

 it "should do something" do
     @article = #set something to enqueue a job
     @article.save
     #can i check if a job is enqueued? can i send this job NOT to the development queue but a different one?
 end
4

3 回答 3

6

正如我所看到的,您不想测试将作业排入队列是否会导致执行被调用 - 我们相信 Resque 会做它应该做的事情。但是,您可以测试 1. 调用 update_related_categories 将作业排入队列。然后,您可以单独测试 2. 调用 perform 的工作人员是否会产生所需的行为。

一般来说,为了测试 Resque,结合 resque-spec 和模拟一个 worker 可以实现上述两个目标。

对于 1,使用 resque-spec,您可以模拟一个工作人员在您的类上调用 perform 方法,然后检查它是否已正确入队:

describe "Calling update_related_categories " do
  before(:each) do
    ResqueSpec.reset!
  end

  it "should enqueue the job" do
    Article.update_related_categories
    CategoriesSorter.should have_queue_size_of(1)
  end
end

对于 2,您可以创建一个 Job(并指定一个与开发队列不同的队列名称)、一个 Resque::Worker 然后将 Worker 分配给 Job:

def run_worker_simulation
  # see Resque::Job api for setting the args you want
  Resque::Job.create('test_queue_name', 'class_name', 'type', 'id')

  worker = Resque::Worker.new('test_queue_name')
  worker.very_verbose = true

  job = worker.reserve
  worker.perform(job)
end

希望能给你一些想法。

于 2012-12-03T18:51:18.527 回答
1

我有

Resque.inline = ENV['RAILS_ENV'] == "test"

这使得所有 resque 任务在测试环境中都是内联的。

为了测试每个作业类,我有单独的规范来分别测试每个作业的执行方法。

于 2012-12-03T18:56:01.077 回答
1

您不应该测试 resque,这是 resque 开发团队的工作,您的应用程序应该只测试您的 perfom 方法是否完成了它必须做的事情。您还可以测试您的模型 Article.rb 是否根据需要将作业排入队列。将真正的作业发送到 resque 是没有用的,您的测试将结束,reque 队列将充满无用的作业。

执行以下操作:

describe 'Article' do
  before(:each) do
    Resque.stub!(:enqueue)
  end

  it 'enqueues the job' do
    cat_id = 1
    Resque.should_receive(:enqueue).once.with(CategoriesWorker, [cat_id])
    Article.create(:category_id => cat_id)
  end
end

describe 'CategoriesSorter' do
  it 'sorts the categories' do
    result = CategoriesSorter.perform([1,4,6,3,2])
    result.should == [1,2,3,4,6]
  end
end

存根或模拟不需要的方法/类

编辑:另外,当您测试文章时,最好将 before(:each) 过滤器设置为存根 resque,这样您的规范就不会将作业发送到真正的队列,我已经编辑了我的答案

于 2012-11-07T13:36:26.400 回答