井原(@ihara2525)です。
以下のような、インスタンスが変更されるとActivejobでElasticsearchのインデックスを更新する処理があり、そのテストを書きたい!ということでやってみました。
after_commit -> { ElasticsearchIndexerJob.perform_later('index', self) if published? }, on: :create
ActiveJob::TestHelperという便利なヘルパが用意されているので、まずはそれをinclude。
spec/support/active_job.rb
RSpec.configure do |config| config.include ActiveJob::TestHelper end
ジョブが保存される場合はその内容をチェック、保存されない場合はキューが空であることをテストしています。
require 'rails_helper' RSpec.shared_examples_for 'indexable' do shared_examples_for 'indexed' do before { clear_enqueued_jobs } it 'is in indexing queue' do subject.save expect(enqueued_jobs.size).to eq 1 expect(enqueued_jobs.first[:job]).to eq ElasticsearchIndexerJob expect(enqueued_jobs.first[:args]).to eq [operation, { '_aj_globalid' => subject.to_global_id.to_s }] expect(enqueued_jobs.first[:queue]).to eq 'default' end end shared_examples_for 'not indexed' do before { clear_enqueued_jobs } it 'is not in indexing queue' do subject.save expect(enqueued_jobs.size).to eq 0 end end context 'when the source is created' do let(:operation) { 'index' } context 'when the source is published' do before { subject.published_at = Time.now } it_behaves_like 'indexed' end context 'when the source is not published' do it_behaves_like 'not indexed' end end end
実際perform_laterには'index', self
を渡しているので(selfはincludeされているモデルのインスタンス)、ActiveJob::TestHelperに用意されているassert_enqueued_withを使って、
assert_enqueued_with(job: ElasticsearchIndexerJob, args['index', subject], queue: 'default') { subject.save }
のように書きたかったのですが、キューにはGlobal IDが入っているため、上記のようにGlobal IDと比較する、若干内部実装によったテストになってしまっています。
これがベストなのかわかりませんが、perform_laterが呼び出されることをチェックするよりは良くなっているように思います!