-
Notifications
You must be signed in to change notification settings - Fork 11
Testing
Sidekiq provides a few options for testing your workers.
Sidekiq provides the following three testing modes:
- A test fake that pushes all jobs into a
jobs
array - An inline mode that runs the job immediately instead of enqueuing it
- The test harness can be disabled. Jobs are pushed to redis.
Sidekiq allows you to dynamically configure the testing harness with the following methods:
require 'sidekiq/testing'
Sidekiq::Testing.fake! # fake is the default mode
Sidekiq::Testing.inline!
Sidekiq::Testing.disable!
Warning: Requiring
sidekiq/testing
will automatically callSidekiq::Testing.fake!
, so your jobs will not go to Redis. Don't requiresidekiq/testing
in any production code.
Each of the above methods also accepts a block. An example:
require 'sidekiq/testing'
Sidekiq::Testing.fake!
# Some tests
Sidekiq::Testing.inline! do
# Some other tests
end
# Here we're back to fake testing again.
To query the current state, use the following methods:
Sidekiq::Testing.enabled?
Sidekiq::Testing.disabled?
Sidekiq::Testing.fake?
Sidekiq::Testing.inline?
Similar to the ActionMailer
testing API, instead of pushing jobs to Redis, Sidekiq pushes them into a jobs
array which you can access. Require the sidekiq/testing
file in your {test,spec}_helper.rb
and set the mode:
require 'sidekiq/testing'
Sidekiq::Testing.fake!
Then assert that jobs were pushed on to the queue:
expect {
HardWorker.perform_async(1, 2)
}.to change(HardWorker.jobs, :size).by(1)
assert_equal 0, HardWorker.jobs.size
HardWorker.perform_async(1, 2)
assert_equal 1, HardWorker.jobs.size
You can execute all queued jobs by draining the queue:
HardWorker.perform_async(1, 2)
HardWorker.perform_async(2, 3)
assert_equal 2, HardWorker.jobs.size
HardWorker.drain
assert_equal 0, HardWorker.jobs.size
To execute all workers' queued jobs:
Sidekiq::Worker.drain_all
If you would like to remove jobs from the queue without actually performing them:
HardWorker.perform_async(1, 2)
HardWorker.clear
assert_equal 0, HardWorker.jobs.size
To clear all workers' jobs:
Sidekiq::Worker.clear_all
This can be useful to make sure jobs don't linger between tests:
RSpec.configure do |config|
config.before(:each) do
Sidekiq::Worker.clear_all
end
end
module SidekiqMinitestSupport
def after_teardown
Sidekiq::Worker.clear_all
super
end
end
class MiniTest::Spec
include SidekiqMinitestSupport
end
class MiniTest::Unit::TestCase
include SidekiqMinitestSupport
end
A testing API for queues is available in 4.0+. This is helpful when the Worker class does not exist in the application being tested. One might enqueue a job using Sidekiq::Client
:
Sidekiq::Client.push(
'class' => 'NonExistentWorker',
'queue' => 'other',
'args' => [1]
)
Since the NonExistentWorker
doesn't exist in the application, we can assert the job made it to the queue:
assert_equal 0, Sidekiq::Queues["other"].size
Sidekiq::Client.push(
'class' => 'NonExistentWorker',
'queue' => 'other',
'args' => [1]
)
assert_equal 1, Sidekiq::Queues["other"].size
assert_equal "NonExistentWorker", Sidekiq::Queues["other"].first["class"]
# Clear an individual queue
Sidekiq::Queues["other"].clear
# Clear all queues (equivalent to Sidekiq::Worker.clear_all)
Sidekiq::Queues.clear_all
To test your worker directly, just treat it like a ruby object. Easy!
work = HardWorker.new
work.perform(1, 2)
You can run Sidekiq workers inline in your tests by requiring the sidekiq/testing
file in your {test,spec}_helper.rb
and setting the mode:
require 'sidekiq/testing'
Sidekiq::Testing.inline!
# or use block mode to avoid leaking the setting into other tests
Sidekiq::Testing.inline! do
HardWorker.perform_async
assert_worked_hard
end
Jobs will then be executed immediately when they are placed on the queue.
You can access the jobs queue from Sidekiq::Extensions::DelayedMailer
(ActionMailer), Sidekiq::Extensions::DelayedModel
(ActiveRecord), or Sidekiq::Extensions::DelayedClass
(everything else) similarly.
assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
MyMailer.delay.send_welcome_email('foo@example.com')
assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
By default, the test harness (in either mode) does not run any server side middleware. You can add middleware to the harness with the following:
Sidekiq::Testing.server_middleware do |chain|
chain.add AwesomeMiddleware
end
Middleware in the Sidekiq::Testing.server_middleware
stack will be run in inline
mode whenever jobs are run and in fake
mode whenever .drain
or .perform_one
are called.
Note that if your middleware is located at lib/sidekiq/middleware/server/awesome_middleware.rb
, as described here, you'll need to require the class like chain.add Sidekiq::Middleware::Server::AwesomeMiddleware
and define it like this in order for it to load properly into the testing chain:
module Sidekiq::Middleware::Server
class AwesomeMiddleware
# do stuff
end
end
Defining the class like class Sidekiq::Middleware::Server::AwesomeMiddleware
won't work properly in the test environment because Sidekiq::Middleware::Server
isn't loaded automatically. You'll probably also have to require the middleware file explicitly.
Sidekiq's API does not have a testing mode, e.g. something like Sidekiq::ScheduledSet.new.each(...)
will always hit Redis. You can use Sidekiq::Testing.disable!
to set up jobs in order to use the API in your tests against a real Redis instance.
Batches are a high-level integration between many jobs. It's difficult to actually run the full batch implementation when testing: I suggest firing callbacks manually rather than trying to set up the batch middleware.
Sidekiq::Testing.inline! do
b = Sidekiq::Batch.new
b.on(:success, SomeCallback)
b.jobs do
# inline will perform jobs immediately
5.times { HardWorker.perform_async }
end
# fire callback manually
SomeCallback.new.on_success(nil, nil)
end
See the rspec-sidekiq gem.
From https://makandracards.com/makandra/28125-perform-sidekiq-jobs-immediately-in-development
# config/environment/test.rb
# perform jobs immediately
config.active_job.queue_adapter = :sidekiq
require 'sidekiq/testing'
Sidekiq::Testing.inline!
...
Home | The Basics | Best Practices | Using Redis | Error Handling | Advanced Options | Problems?
This wiki is tracked by git and publicly editable. You are welcome to fix errors and typos. Any defacing or vandalism of content will result in your changes being reverted and you being blocked.