【问题标题】:RSpec + Sidekiq: NoMethodError: undefined method 'jobs' MyImportJobRSpec + Sidekiq:NoMethodError:未定义的方法'jobs' MyImportJob
【发布时间】:2018-07-10 19:37:41
【问题描述】:

我正在尝试在 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>>

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

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

我的rails_helper.rb 文件有:

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

提前致谢!

【问题讨论】:

  • 旁注:这个问题的测试相当没用。您正在测试 sidekiq 的功能(重复工作)。假设 sidekiq “正常工作”是非常安全的,因此您的测试应该检查您的实际逻辑(“当且仅当发布有效的注册表单时检查是否安排了欢迎电子邮件”)
  • 是的,这是下一步,我只是想知道如何才能使基本测试正常工作。现在我知道这是subjects 的错。感谢您的建议!
  • 是的,宝贝步骤。只是确保。 :)

标签: ruby-on-rails rspec sidekiq


【解决方案1】:

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

默认情况下,如果最外层示例组的第一个参数 (描述或上下文块)是一个类,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

【讨论】:

    【解决方案2】:

    预期的 ArgumentError,得到 #&lt;NoMethodError: undefined method 'perform_async' for #&lt;MyImportJob:0x007f80b6d73f50&gt;&gt;

    perform_async 是工人类本身的方法。

    MyImportJob.perform_async(...)
    

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

    同样的原因。这是一个工人类的方法。

    【讨论】:

    • 主题是MyImportJob,所以它应该是正确的。如果我传入类名,则行为相同
    • @DaniG2k:是吗?你怎么知道? (错误信息另有说明)
    • 啊!你是对的...我检查了 subjectbinding.pry 的内容,并认为是 MyImportJob
    猜你喜欢
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多