行動すれば次の現実

ほどよくモダンなシステム開発を目指しています。メインテーマは生産性、Ruby、Javascriptです。

Sidekiqで実装したWorkerをRSpecでテストする

Sidekiqで実装したWorkerクラスのRSpecでテストする方法をまとめました。

SidekiqをRSpecでテストする方法

Sidekiqのテスト手法には主に以下の2種類があります。

Sidekiq::Testing.fake!を使用したテスト

キューへのジョブ登録(エンキュー)から、ジョブの実行までの流れをテストしたい場合などに適しています。 非同期処理を見立てたテストケースを実行することができます。

Sidekiq::Testing.inline!を使用したテスト

キューには登録せずにジョブを即時実行します。 同期処理のような動きになりますので、ジョブを実行した結果をassertしたい場合などに適しています。

Sidekiq::Testing.fake!のテストコード

Sidekiq::Testing.fake!はジョブをエンキューする際に、redisを使用するのはなく、redisに見立てた仮想的なキューとして配列(Array)を使用します。

# ワンライナーでの記法
expect {
  SampleWorker.perform_async(10)
}.to change(SampleWorker.jobs, :size).by(1)

# 上記と同じ内容のテストです
assert_equal 0, SampleWorker.jobs.size
SampleWorker.perform_async(10)
assert_equal 1, SampleWorker.jobs.size

上記はジョブをエンキューするまでのテストになります。 ジョブ自体はまだ実行されていません。

drainでキューに積まれたジョブを実行することができます。

assert_equal 0, SampleWorker.jobs.size
SampleWorker.perform_async(10)
assert_equal 1, SampleWorker.jobs.size
SampleWorker.drain # ジョブが実行されます
assert_equal 0, SampleWorker.jobs.size

SampleWorkerが実際に実行されますので、必要に応じてテストデータを用意したりmock化したりする必要があります。

Sidekiq::Testing.fake!を使用していると、キューに未実行のジョブが残ってしまうことがあります。 そのためテスト毎に下記のようにキューをクリアする必要があります。

Sidekiq::Worker.clear_all

以上を踏まえると、RSpecの全体像はこのような形になるかと思います。

require 'rails_helper'
require 'sidekiq/testing'
RSpec.describe SampleWorker, type: :worker do
  describe 'testing worker' do
    before do
      Sidekiq::Worker.clear_all
    end
    example 'エンキューされたジョブが実行されること' do
      Sidekiq::Testing.fake!
      expect { SampleWorker.perform_async }.to change { SampleWorker.jobs.size }.by(1)
      SampleWorker.drain # ジョブの実行
      assert_equal 0, SampleWorker.jobs.size
      # 実行結果の確認などあれば適宜記述
    end
  end
end

Sidekiq::Testing.inline!のテストコード

Sidekiq::Testing.inline!はキューには登録しないため即座に実行されます。

RSpec.describe SampleWorker, type: :worker do
  describe 'testing worker' do
    example 'ジョブの結果が正しいこと' do
      Sidekiq::Testing.inline! do
        SampleWorker.perform_async
        # ここに想定結果を記述します。
      end
    end
  end
end

同期処理のような振る舞いになりますので、ジョブが実行された結果をassertしたい場合などに適しています。

参考

Testing · mperham/sidekiq Wiki · GitHub