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!はキューには登録しないため即座に実行されます。
require 'sidekiq/testing' require 'rails_helper' RSpec.describe SampleWorker, type: :worker do describe 'testing worker' do example 'ジョブの結果が正しいこと' do Sidekiq::Testing.inline! do SampleWorker.perform_async # ここに想定結果を記述します。 end end end end
同期処理のような振る舞いになりますので、ジョブが実行された結果をassertしたい場合などに適しています。