Testing sidekiq perform_in with RSpec 3

RSpec 3 and sidekiq 3.2.1. And I have installed sidekiq and rspec-sidekiq correctly.

Let's say I have a worker named WeatherJob

that will change the weather status from sunny

to rainy

:

class WeatherJob
  include Sidekiq::Worker

  def perform record_id
    weather = Weather.find record_id

    weather.update status: 'rainy'
  end
end

      

I am using this worker as follows:

WeatherJob.perform_in 15.minutes, weather.id

...

In the spec, I use Timecop to determine the time:

require 'rails_helper'

describe WeatherJob do
  let(:weather) { create :weather, status: 'sunny' }
  let(:now)     { Time.current }

  it 'enqueue a job' do
    expect {
      WeatherJob.perform_async weather.id
    }.to change(WeatherJob.jobs, :size).by 1
  end

  context '15 mins later' do
    before do
      Timecop.freeze(now) do
        Weather.perform_in 15.minutes, weather.id
      end
    end

    it 'update to rainy' do
      Timecop.freeze(now + 16.minutes) do
        expect(weather.status).to eq 'rainy'
      end
    end
  end
end

      

I saw that there is work in the array Weather.jobs

. And the time is correct 16 minutes after. But it didn't do the job? Any tips? Thank!

+3


source to share


3 answers


Sidekiq has three test modes: disabled, fake, and built-in. The default is fake, which just puts all jobs in the job array and the behavior you see. Inline mode starts the job immediately, rather than forcing it to run.

To force Sidekiq to run an inline job during a test, wrap the test code in a block Sidekiq::Testing.inline!

:



before do
  Sidekiq::Testing.inline! do
    Timecop.freeze(now) do
      Weather.perform_in 15.minutes, weather.id
    end
  end
end

      

For more information on testing Sidekiq, see the official testing wiki page .

+5


source


If you want to test an assignment whether it should run after 15 minutes or not, you must split the test cases into two parts. In the first part, you have to check if it will insert a job that will be active for 15 minutes (using mocks). The second part is whether the task was done correctly or not.



+2


source


Do this in two steps. First check that the job was scheduled, then run the job in strict mode without delay. Here's an example

it "finishes auction  (async)" do
  auction = FactoryGirl.create(:auction)
  auction.publish!

  expect(AuctionFinishWorker).to have_enqueued_sidekiq_job(auction.id).at(auction.finishes_at)
end

it "finishes auction  (sync)" do
  auction = FactoryGirl.create(:auction)
  auction.publish!

  Sidekiq::Testing.inline! do
    AuctionFinishWorker.perform_async(auction.id)
  end

  auction.reload
  expect(auction).to be_finished
end

      

have_enqueued_sidekiq_job

the method comes from the rspec-sidekiq gem. They are actively developing in the industry develop

. Make sure you enable it like this.

  gem 'rspec-sidekiq', github: "philostler/rspec-sidekiq", branch: "develop"

      

+1


source







All Articles