Railsでサービスを開発していると、バックグラウンドで処理を実行するジョブを実装することがあるかと思います。
そんなとき、いつもテストの書き方を忘れてしまうので、内容の理解と整理のために備忘録として記事を書こうと思います。
まずはそもそもどういったものをテストするべきかを整理してみたいともいます。
ジョブ自身は基本的に同期的に実行しているモデルまたはメール送信などの処理をバックグラウンドで非同期に実行することが多いと思います。
なので、ユニットテストでは基本的には正確に意図したジョブが呼び出されているか、ということさえ確認できればよいのではないかと思います。
もちろんこれはジョブ実行メソッドの中に余計な処理が書かれていないことが前提となります。
それでは簡単なサンプルと解説を書いていきたいと思います。
まずは config.active_job.queue_adapter
を設定します。ここでは :test
を指定していますが、ご自身の環境に合わせて設定してください。
Rails.application.configure do
# snip...
config.active_job.queue_adapter = :test
end
それではテストコードを書いていきたいと思います。モデル、ジョブ、テストの順番にコードを書いていきます。
class Thing < ApplicationRecord
after_commit :do_something_job
def do_something
# Do something...
end
private
def do_something_job
ThingJob.perform_later(self)
end
end
class ThingJob < ActiveJob::Base
def perform(thing)
thing.do_something
end
end
require 'rails_helper'
RSpec.describe Thing, type: :model do
include ActiveJob::TestHelper
describe '#do_something_job' do
it 'enqueues `ThingJob`' do
expect {
Thing.create!
}.to have_enqueued_job(ThingJob)
end
end
end
普段からRailsを利用している開発者からしたらどうということのないコードかと思います。
処理の流れとしては、Thing
の作成(または更新)処理が行われると、commit をフックとして do_something_job
の中で ThingJob
が実行されます。
ThingJob
では Thing#do_something
が実行されます。
最初に書いたとおり、ここではコールバックの実行とともに想定通りのジョブがキューに追加されるかどうか、という部分を確認しています。
ActiveJob::TestHelper
は実際にはなくても動くのですが、モジュールの中でジョブの初期化処理をやってくれているので、特に問題がなければインクルードしておくと良いかと思います。
勝手に初期化して欲しくないということであれば、上記のヘルパーを参考にして初期化処理をかくとよいかと思います。
と、ここまで書いておいてアレなのですが、実はRSpecのドキュメントにその他の細かいマッチャーなどもしっかり記載されています。
さらに詳細な条件でテストをしたい場合には、RSpecのドキュメントを参考にしてみてください。
すべてのケースをテストでカバーできるということはあり得ないのですが、それでも基本的なケースをいくつか抑えておくだけで変更の際の安心感が変わってきます。
苦手意識を持たず、満遍なくテストを書くことができるようにしていきましょう。