为运动鞋和Rabbitmq测试RSpec

时间:2019-01-05 04:38:39

标签: ruby-on-rails rabbitmq web-worker sneakers

我最近一直在使用Rabbitmq和Sneakers Workers开发Message Queue。我看过本指南https://github.com/jondot/sneakers/wiki/Testing-Your-Worker

但是我仍然不知道如何为他们开发测试。如果有任何建议,我非常感谢。

1 个答案:

答案 0 :(得分:1)

建议的指南包含Sneakers::Testing模块,用于存储所有已发布的消息。为此,您需要修补/存根方法Sneakers::Publisher#publish才能将发布的消息保存到Sneakers::Testing.messages_by_queue中。然后将这些数据用于期望值或以某种方式将其提供给工作者类。

在大多数情况下,您仅需要内联执行即可延迟规格中的作业。因此,只需修补Sneakers::Publisher#publish即可按队列名称获取工作程序类,并使用收到的有效负载消息调用其work方法。初始设置:

# file: spec/support/sneakers_publish_inline_patch.rb

# Get list of all sneakers workers in app.
# You can just assign $sneakers_workers to your workers:
#
#     $sneakers_workers = [MyWorker1, MyWorker2, MyWorker3]
#
# Or get all classes where included Sneakers::Worker
# Note: can also load all classes with Rails.application.eager_load!
Dir[Rails.root.join('app/workers/**/*.rb')].each { |path| require path }
$sneakers_workers = ObjectSpace.each_object(Class).select { |c| c.included_modules.include? Sneakers::Worker }

# Patch method `publish` to find a worker class by queue and call its method `work`.
module Sneakers
  class Publisher
    def publish(msg, opts)
      queue = opts[:to_queue]
      worker_class = $sneakers_workers.find { |w| w.queue_name == queue }
      worker_class.new.work(msg)
    end
  end
end

或规范中一个工人的存根方法:

allow_any_instance_of(Sneakers::Publisher).to receive(:publish) do |_obj, msg, _opts|
  MyWorker.new.work(msg)
end

或添加共享上下文以方便方式启用内联作业执行:

# file: spec/support/shared_contexts/sneakers_publish_inline.rb

shared_context 'sneakers_publish_inline' do
  let(:sneakers_worker_classes) do
    Dir[Rails.root.join('app/workers/**/*.rb')].each { |f| require f }
    ObjectSpace.each_object(Class).select { |c| c.included_modules.include? Sneakers::Worker }
  end

  before do
    allow_any_instance_of(Sneakers::Publisher).to receive(:publish) do |_obj, msg, opts|
      queue = opts[:to_queue]
      worker_class = sneakers_worker_classes.find { |w| w.queue_name == queue }
      raise ArgumentError, "Cannot find Sneakers worker class for queue: #{queue}" unless worker_class
      worker_class.new.work(msg)
    end
  end
end

然后仅在需要内联作业执行的规范中添加include_context 'sneakers_publish_inline'