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

Dan*_*G2k 1 rspec ruby-on-rails sidekiq

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

我的代码如下所示:

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

  def perform(params)
    # Do magic
  end
end
Run Code Online (Sandbox Code Playgroud)

和规范:

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
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误:

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

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

我认为perform_async只要我include Sidekiq::Worker在我的工作人员中包含该行,Sidekiq 就应该默认提供,这是正确的吗?如果我只是使用,则第一个测试通过,perform但我希望它通过perform_async我在代码库中使用的测试。

至于第二种,我不明白为什么jobs测试对象没有方法。有什么线索吗?

我的rails_helper.rb文件有:

require 'sidekiq/testing'
Sidekiq::Testing.fake!
Run Code Online (Sandbox Code Playgroud)

提前致谢!

小智 5

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

默认情况下,如果最外层示例组(描述或上下文块)的第一个参数是一个类,则 RSpec 创建该类的一个实例并将其分配给主题

ref:RSpec 的主题和 let 之间有什么区别?什么时候应该使用它们?

这意味着它会创建您的工作人员的实例。这样你就不能调用perform_asyncand 了jobs

要解决您的问题,请将其明确定义如下:

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
Run Code Online (Sandbox Code Playgroud)