Skip to content

inkstak/rspec-sidekiq_pro

Repository files navigation

RSpec for Sidekiq Pro

Gem Version CI Status Ruby Style Guide Maintainability Test Coverage

Installation

bundle add rspec-sidekiq_pro --group=test

Configuration

rspec/sidekiq_pro requires sidekiq/testing by default so there is no need to include it.

It also means that Sidekiq in set to fake mode by default. Take a look at Sidekiq wiki for more details.

If you wish to start each spec without enqueued jobs or batches:

require "rspec/sidekiq_pro"

RSpec.configure do |config|
  config.before do
    Sidekiq::Queues.clear_all
    RSpec::SidekiqPro::Batches.clear_all
  end
end

Usage

Two matchers are provided:

  • enqueue_sidekiq_job supports block expectation
  • have_enqueued_sidekiq_job supports value expectation
it do
  expect { SampleJob.perform_async }.to enqueue_sidekiq_job(SampleJob)
end
it do
  SampleJob.perform_async
  expect(SampleJob).to have_enqueued_sidekiq_job
end

Both matchers provide the same chainable methods:

  • .with
  • .once
  • .twice
  • .exactly(n).times
  • .more_than(n).times
  • .less_than(n).times
  • .at_least(n).times
  • .at_most(n).times
  • .in
  • .at
  • .within_batch
  • .without_batch

Checking arguments

it do
  expect { SampleJob.perform_async(1, 2, 3) }
    .to enqueue_sidekiq_job(SampleJob).with(1, 2, 3)
end
it do
  SampleJob.perform_async(1, 2, 3)
  expect(SampleJob).to have_enqueued_sidekiq_job.with(1, 2, 3)
end

Checking counts

it do
  expect { SampleJob.perform_async }
    .to enqueue_sidekiq_job(SampleJob).once
end
it do
  expect { 
    2.times { SampleJob.perform_async }
  }.to enqueue_sidekiq_job(SampleJob).twice
end
it do
  expect { 
    3.times { SampleJob.perform_async }
  }.to enqueue_sidekiq_job(SampleJob).exactly(3).times
end
it do
  expect {
    10.times { SampleJob.perform_async }
  }.to enqueue_sidekiq_job(SampleJob).more_than(5).times
end

Be careful when checking both counts and arguments:

it do
  expect { 
    SampleJob.perform_async.with(1)
    SampleJob.perform_async.with(2)
  } 
    .to  enqueue_sidekiq_job(SampleJob).twice
    .and enqueue_sidekiq_job(SampleJob).once.with(1)
    .and enqueue_sidekiq_job(SampleJob).once.with(2)
end

Checking schedules

it do
  expect { 
    SampleJob.perform_in(5.minutes)
  }.to enqueue_sidekiq_job(SampleJob).in(5.minutes)
end
it do
  expect { 
    SampleJob.perform_at(10.minutes.from_now)
  }.to enqueue_sidekiq_job(SampleJob).at(10.minutes.from_now)
end

Time matching is performed to the second, if you have code that takes some time to be executed consider using Timecop.

Batches

it do
  expect { 
    SampleJob.perform_async
  }.to enqueue_sidekiq_job(SampleJob).without_batch
end
it do
  expect { 
    batch = Sidekiq::Batch.new
    batch.jobs { SampleJob.perform_async }
  }.to enqueue_sidekiq_job(SampleJob).within_batch
end
it do
  expect { start_some_complex_workflow }
    .to enqueue_sidekiq_job(SampleJob).twice.within_batch { |batch|
      expect(batch).to have_attributes(description: "Complex Workflow first step")
    }
end

within_batch and without_batch require Sidekiq::Testing to be enabled.

When Sidekiq::Testing is enabled, every batch is pushed to RSpec::SidekiqPro::Batches instead of Redis.

it do
  batch = Sidekiq::Batch.new
  batch.jobs { SampleJob.perform_async }

  expect(RSpec::SidekiqPro::Batches.first.bid).to eq(batch.bid)
end

Contributing

  1. Don't hesitate to submit your feature/idea/fix in issues
  2. Fork the repository
  3. Create your feature branch
  4. Ensure RSpec & Rubocop are passing
  5. Create a pull request

Tests & lint

bundle exec rspec
bundle exec rubocop
bundle exec standardrb

All of them can be run with:

bundle exec rake

License & credits

Please see LICENSE for further details.

Inspired by the philostler/rspec-sidekiq & pirj/rspec-enqueue_sidekiq_job

Contributors: ./graphs/contributors