Sending an email with Sidekiq RSpec Test failed because Array is empty and could not change from 0 to 1

*爱你&永不变心* 提交于 2021-01-29 02:58:57

问题


I am trying to test sending an email with Sidekiq and I am having an error which means it doesn't enqueue since my test shows it didn't change from 0 to 1 in size. Could it be I am missing something out or how can I fix this?

Error

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

This shows Sidekiq::Worker.jobs is empty array and it is understandable why it failed but I do not know how I could fix this.

[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!

回答1:


You probably should use the method count instead of size:

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

Take a look at the size implementation:

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

Also take a look on the matcher implementation (https://github.com/rspec/rspec-expectations/blob/master/lib/rspec/matchers/built_in/change.rb#L82:L85)

I'm guessing that the receiver (Sidekiq::Worker.jobs in your case) will be evaluated once, and then the size would be called twice on the same objects collection, without reloading.

One other approach you could take would be

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

But this would be a bit wasteful in case you have more records in the DB, because each time the AR objects will need to be created (and they're not used)



来源:https://stackoverflow.com/questions/59059988/sending-an-email-with-sidekiq-rspec-test-failed-because-array-is-empty-and-could

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!