RSpec + Sidekiq:NoMethodError:未定义的方法' jobs' MyImportJob

时间:2018-01-31 16:04:52

标签: ruby-on-rails rspec sidekiq

我正在尝试在Rails 4.2.4应用程序中为RSpec + Sidekiq编写一些规范,但遇到了一些问题。

我的代码如下所示:

class MyImportJob
  include Sidekiq::Worker
  sidekiq_options queue: :default

  def perform(params)
    # Do magic
  end
end

和规范:

describe MyImportJob, type: :job do
  let(:panel) { create(:panel) }

  describe '#perform' do
    context 'unsuccessfully' do
      it 'raises ArgumentError if no panel param was passed' do
        expect {subject.perform_async()}.to raise_error(ArgumentError)
      end
    end

    context 'successfully' do
      it 'given a panel, it increases the job number' do
        expect {
          subject.perform_async(panel_id: panel.id)
        }.to change(subject.jobs, :size).by(1)
      end
    end
  end
end

但我收到以下错误:

Failure/Error: }.to change(subject.jobs, :size).by(1)
  NoMethodError:
    undefined method `jobs' for #<MyImportJob:0x007f80b74c5c18>

Failure/Error: expect {subject.perform_async()}.to raise_error(ArgumentError)
  expected ArgumentError, got #<NoMethodError: undefined method `perform_async' for #<MyImportJob:0x007f80b6d73f50>>

我相信Sidekiq默认提供perform_async,只要我在工作人员中加入include Sidekiq::Worker行,这是正确的吗?如果我只是使用perform,那么第一次测试就会通过,但我希望它能通过perform_async,这是我在代码库中使用的。

至于第二种,我不明白为什么测试对象没有方法jobs。关于那个的任何线索?

我的rails_helper.rb文件有:

require 'sidekiq/testing'
Sidekiq::Testing.fake!

提前致谢!

2 个答案:

答案 0 :(得分:4)

如果您未明确定义subject,则rspec将按以下规则创建主题:

  

默认情况下,如果是最外层示例组的第一个参数   (describe或context block)是一个类,RSpec创建一个实例   该课程并将其分配给主题

参考:What's the difference between RSpec's subject and let? When should they be used or not?

这意味着它会创建您的工作人员的实例。因此,您无法致电perform_asyncjobs

要解决您的问题,请按以下方式明确定义:

describe MyImportJob, type: :job do
  let(:panel) { create(:panel) }

  subject { MyImportJob }

  describe '#perform' do
    context 'unsuccessfully' do
      it 'raises ArgumentError if no panel param was passed' do
        expect {subject.perform_async()}.to raise_error(ArgumentError)
      end
    end

    context 'successfully' do
      it 'given a panel, it increases the job number' do
        expect {
          subject.perform_async(panel_id: panel.id)
        }.to change(subject.jobs, :size).by(1)
      end
    end
  end
end

答案 1 :(得分:1)

  

预期的ArgumentError,得到#<NoMethodError: undefined method 'perform_async' for #<MyImportJob:0x007f80b6d73f50>>

perform_async是工人类本身的一种方法。

MyImportJob.perform_async(...)
  

我不明白为什么测试对象没有方法jobs

同样的确切原因。这是工人阶级的一种方法。