# Testing Sidekiq in Ruby on Rails: A Comprehensive Guide

## Introduction

Sidekiq is a powerful tool for handling asynchronous jobs in Ruby. It can be easily integrated with Ruby on Rails applications to streamline background tasks. With Ruby on Rails, there are two main options for using Sidekiq:

1. Integrate Sidekiq with Active Job and utilize the helpers provided by Rails
    
2. Use plain Sidekiq without Active Job
    

In this article, we will focus on using Sidekiq without Active Job, which can be 2-20 times faster than using it with Active Job. We will cover how to configure Sidekiq with Ruby on Rails application, how to generate jobs, and how to test them. Let's get started!

## Config Sidekiq in a Ruby on Rails Application

1. Add sidekiq to the Gemfile.
    

```ruby
# Gemfile
gem 'sidekiq'

group :test do
  gem 'rspec-sidekiq'
end
```

2\. Configure the queue adapter for Rails:

```ruby
# config/application.rb
config.active_job.queue_adapter = :sidekiq
```

With this configuration, Sidekiq is now set up for your Ruby on Rails application. Next, let's generate our first job:

```ruby
rails generate sidekiq:job example
```

## **Generate a New Job**

We will create a simple service that runs a job asynchronously and a job that updates an employee's position:

```ruby
# app/services/example.rb
class Example
  def initialize(employee_id)
    @employee_id = employee_id
  end
  
  def call
    ExampleJob.perform_async(@employee_id)
  end
end
```

```ruby
# app/sidekiq/example_job.rb
class ExampleJob
  include Sidekiq::Job

  def perform(employee_id)
    employee = Employee.find(employee_id)

    employee.update!(position: 'CEO')
  end
end
```

## **Sidekiq testing**

With Sidekiq, we have three strategies for testing our code:

1. Fake mode (default): Jobs are pushed into an array instead of Redis.
    
2. Inline mode: Code is executed synchronously.
    
3. Disable mode: Jobs are pushed into Redis.
    

For service testing, I recommend using the default fake mode. For job testing, I recommend using inline mode, as it tests the exact behavior of the worker.  

### **Fake Testing**

```ruby
subject(:job) { ExampleJob.perform_async(employee_id) }

it 'queues the job' do
	expect { job }.to change(Sidekiq::Queues['default'], :size).by(1)
end

it 'queues the job2' do
	expect { job }.to change(ExampleJob.jobs, :size).by(1)
end

it 'queues the job3 with rspec-sidekiq helper' do
    job
    expect(described_class).to have_enqueued_sidekiq_job(employee.id)
end
```

Now, let's execute the code and check if the worker's code is working as expected. To do this, we will use the ***drain*** method, which processes all jobs:

```ruby
expect do
    job
    described_class.drain
end.to change { employee.reload.position }.from('resource').to('CEO')
```

We can also execute the job using the `perform_inline` method, which will execute the code synchronously:

```ruby
it 'raise errors2' do
    expect { described_class.perform_inline(employee_id) }.to raise_error(ActiveRecord::RecordNotFound)
end
```

Lastly, we can use the RSpec hook with custom metadata:

```ruby
it 'raise errors3', :inline_sidekiq_testing do
	expect { job }.to raise_error(ActiveRecord::RecordNotFound)
end
---
rails_helper.rb

config.around(:each, :inline_sidekiq_testing) do |example|
    Sidekiq::Testing.inline! do
    	example.run
    end
end
```

### **Testing with Disable Mode**

This mode can be useful for integration tests when we want to check if the job was queued in Redis.

```ruby
it 'enqueue job' do
    Sidekiq::Testing.disable! do
    	expect { service }.to change { Sidekiq::Queue.new.size }.by(1)
    end
end
```

You can refactor the above code as follows:

```ruby
config.around(:each, :disable_sidekiq_testing) do |example|
    Sidekiq::Testing.disable! do
      example.run
    end
  end
  
  it 'enqueue job2', :disable_sidekiq_testing do
 	 expect { service }.to change { Sidekiq::Queue.new.size }.by(1)
  end
```

You can also test it in this way:

```ruby
it 'enqueue job3', :disable_sidekiq_testing do
  expect { service }.to change {
    Sidekiq::Queue.new.select do |job|
      job.klass == 'ExampleJob'
      job.args == [employee_id_param]
      job.queue == 'default'
    end.size
  }.by(1)
end
```

## **Tips and Sidekiq Web UI**

At the end of this guide, I want to introduce you to the Sidekiq Web UI. You can implement it by adding the following your routes:

```ruby
# config/routes.rb
require 'sidekiq/web'

Rails.application.routes.draw do
  mount Sidekiq::Web => '/sidekiq'
  root 'pages#home'
end
```

With the Sidekiq Web UI, you can monitor the status of your jobs and gain insights into the performance of your background tasks.

![](https://mateusz-bialowas.ghost.io/content/images/2023/04/CleanShot-2023-04-16-at-19.11.24@2x.png align="left")

Now you have a comprehensive guide on how to test Sidekiq in a Ruby on Rails application. Good luck and happy testing!

### **Resources**

[https://github.com/sidekiq/sidekiq/wiki/Testing](https://github.com/sidekiq/sidekiq/wiki/Testing)

[https://gist.github.com/mateuszbialowas/b9944a3c0a11c80e25aceb4e0483afe1](https://gist.github.com/mateuszbialowas/b9944a3c0a11c80e25aceb4e0483afe1)
