【问题标题】:How do you separate test queues and real queues when testing Resque (with rspec and rails?)测试 Resque 时如何区分测试队列和真实队列(使用 rspec 和 rails?)
【发布时间】:2012-10-27 01:15:36
【问题描述】:

我想测试一些 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,它是在保存测试中创建的对象的文章模型中调用的。

示例代码:

Article.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

【问题讨论】:

标签: ruby-on-rails ruby-on-rails-3 rspec rspec2 resque


【解决方案1】:

我有

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

这使得所有 resque 任务都在 test 环境中内联。

为了测试每个 Job 类,我有单独的规范来分别测试每个 jobperform 方法。

【讨论】:

    【解决方案2】:

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

    对于一般的 Resque 测试,结合 resque-spec 和模拟 worker 可以实现上述两个目标。

    对于1,使用resque-spec,你可以模拟一个worker在你的类上调用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
    

    希望能给你一些想法。

    【讨论】:

      【解决方案3】:

      您不应该测试 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,这样您的规范就不会将作业发送到真正的队列,我已经编辑了我的答案

      【讨论】:

        猜你喜欢
        • 2018-03-12
        • 2010-11-07
        • 1970-01-01
        • 2017-11-17
        • 2015-05-11
        • 1970-01-01
        • 1970-01-01
        • 2021-04-28
        • 1970-01-01
        相关资源
        最近更新 更多