使用元编程为多个工人编写单个规范

时间:2017-07-14 07:20:00

标签: ruby-on-rails ruby rspec

我写了一个sidekiq工人规范。所以现在我们有四个工人几乎相同的规格。所有规范都将测试some_method并检查作业是否已被清除。

我的示例工作者代码:

RSpec.describe HardWorker do
  subject(:worker) { described_class.new }

  describe "perform" do
    let(:some_id) { instance_double("String") }

    it "calls Hard working operation" do
      expect(HardWorkingOperation).to receive(:one_method)
        .with(some_id: some_id)

      worker.perform(some_id)
    end

    it "enqueues a HardWork worker" do
      HardWorker.perform_async(some_id)
      expect(HardWorker.jobs.size).to eq 1
    end
  end
end

第二个样本规范:

RSpec.describe AnotherWorker do
  subject(:worker) { described_class.new }

  describe "perform" do
    let(:key1){double("Integer")}
    let(:key2){double("String")}
    let(:options) do 
      {
        :key1 => key1, 
        :key2_ref => key2
      }
    end

    it "calls method_data" do
      expect(AnotherOperation).to receive(:another_method)
        .with(options["key1"], options["key2"])

      worker.perform(options)
    end

    it "enqueues a Another worker" do
        AnotherWorker.perform_async(options)
        expect(AnotherWorker.jobs.size).to eq 1
    end
  end
end

我想写一个单一的规范来测试所有接收某种方法的工人(可能各自不同)并且该工作已经入队。 我该怎么做才能做到最好?有什么建议值得赞赏吗?

1 个答案:

答案 0 :(得分:3)

您可以使用shared examples。假设它们都有一个“操作”类,它将执行call,可能是这样的:

shared_examples_for "a sidekiq worker" do |operation_klass|
  subject(:worker) { described_class.new }

  describe "perform" do
    let(:some_id) { instance_double("String") }

    it "calls some operation" do
      expect(operation_klass).to receive(:call).with(some_id: some_id)
      worker.perform(some_id)
    end

    it "enqueues a worker" do
      described_class.perform_async(some_id)
      expect(described_class.jobs.size).to eq 1
    end
  end
end

RSpec.describe HardWorker do
  it_behaves_like "a sidekiq worker", HardWorkingOperation
end

如果您还需要检查call是否使用每个工作者的不同参数集来完成,您可以将其作为哈希传递。但在那一点上,你应该问自己,如果真的应该提取出那个规范:P

shared_examples_for "a sidekiq worker" do |operation_klass, ops_args|
  ..
  expect(operation_klass).to receive(:call).with(ops_args)
  ..
end

it_behaves_like "a sidekiq worker", HardWorkingOperation, { some_id: some_id }