使用Sidekiq RSpec测试发送电子邮件失败,因为数组为空并且无法从0更改为1

问题描述 投票:0回答:1

我正在尝试使用Sidekiq测试发送电子邮件,但出现错误,这意味着它没有进入队列,因为我的测试表明它的大小没有从0更改为1。可能是我遗漏了一些东西,或者该如何解决?

错误

expected `Array#size` to have changed by 1, but was changed by 0

  0) Sending Mail sends email to sidekiq
     Failure/Error:
       expect do
         OrderPointsMailer.paid_order_email(customer_detail.id).deliver_later
       end.to change(Sidekiq::Worker.jobs, :size).by(1)

       expected `Array#size` to have changed by 1, but was changed by 0
     # ./spec/requests/order_points_mailer_spec.rb:9:in `block (2 levels) in <top (required)>'

1 example, 1 failure, 0 passed

binding.pry

这显示Sidekiq::Worker.jobsempty array,它为什么会失败是可以理解的,但我不知道该如何解决。

[1] pry(#<RSpec::ExampleGroups::SendingMailWithSidekiq>)>Sidekiq::Worker.jobs
=> []

app / jobs / order_points_job.rb

# frozen_string_literal: true

class OrderPointsJob < ApplicationJob
  def perform(customer_email)
    customer_detail = CustomerDetail.find_by(email: customer_email)
    return unless customer_detail

    OrderPointsMailer.paid_order_email(customer_detail.id).deliver_later # This call send email to sidekiq process
  end
end

RSpec

# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'Sending Mail with Sidekiq', type: :request do
  it 'sends email to sidekiq' do
    customer_detail = create(:customer_detail)

    expect do
      OrderPointsMailer.paid_order_email(customer_detail.id).deliver_later
    end.to change(Sidekiq::Worker.jobs, :size).by(1)
  end
end

rails_helper.rb

require 'sidekiq/testing'
Sidekiq::Testing.fake!
ruby-on-rails rspec rspec-rails
1个回答
0
投票

您可能应该使用方法count而不是size

.to change(Sidekiq::Worker.jobs.reload, :count).by(1)

看看size实现:

From: /home/toptal/.rvm/gems/ruby-2.5.5/gems/activerecord-6.0.0/lib/active_record/relation.rb @ line 260:
Owner: ActiveRecord::Relation
Visibility: public
Number of lines: 3

def size
  loaded? ? @records.length : count(:all)
end

也请查看匹配器实现(https://github.com/rspec/rspec-expectations/blob/master/lib/rspec/matchers/built_in/change.rb#L82:L85

我猜测接收器(在您的情况下为Sidekiq::Worker.jobs)将被评估一次,然后将在相同的对象集合上两次调用size,而无需重新加载。

您可以采用的另一种方法是

.to change { Sidekiq::Worker.jobs.reload.size }.by(1)

但是如果您在数据库中有更多记录,这将有点浪费,因为每次都需要创建AR对象(并且不使用它们)

© www.soinside.com 2019 - 2024. All rights reserved.