patorashのブログ

方向性はまだない

ActiveJobのテスト周りの見直しで学んだことのメモ

最近テストが不安定になって、その修正をしていっていたらActiveJobが絡むあたりがまた不安定になったので原因を探ろうとしたのだけれど、ActiveJobのテストの設定周りなんて久々すぎて忘れまくっていたのでここで一旦整理しておく。

テストでActiveJobを同期的に扱う

ActiveJobのqueue_adapterの設定は、environmentsの各ファイルで行うべき、だそう。コメントでそう書いてあった。

# Use a real queuing backend for Active Job (and separate queues per environment)

production.rbなど

# Use a real queuing backend for Active Job (and separate queues per environment)
config.active_job.queue_adapter = :resque
config.active_job.queue_name_prefix = "project_#{Rails.env}"

test.rb

テストでは、queue_adapterを:asyncに設定する。以前は:inlineだったらしい。

blog.bigbinary.com

# Use a real queuing backend for Active Job (and separate queues per environment)
config.active_job.queue_adapter = :async
config.active_job.queue_name_prefix = "project_#{Rails.env}"

こうするとキューに入ったと同時に実行されるっぽい。

テストでもResqueを使いたい!

あんまりこだわることはないのかもしれないが、テストでもqueue_adapterに:resqueを使いたい場合は、:resqueを指定した上で、Resqueの設定をinlineにすればよかった。 Resqueの設定は、config/initializers/resque.rbで行なっていたのでそこに追記した。

Resque.redis = Redis.new(host: "localhost", port: ENV.fetch("REDIS_PORT", 6379)
Resque.inline = true if Rails.env.test?

こうすると、Resqueもキューに入ったと同時にジョブを実行してくれる。

ActiveJob::TestHelperを使う

もう一つ方法がある。それは、ActiveJob::TestHelperを使う方法だ。spec/rails_helper.rbなどで読み込む。

config.include ActiveJob::TestHelper

実はすでにこちらを使っていた。しかし、なぜかジョブが実行されなかったようだったので、上記の設定を色々といじったりしていたのだが、何も変わらなかった。 しかしそれは当然で、ActiveJob::TestHelperを読み込むと、queue_adapterがconfig/environments.test.rbに設定したものではなく、TestAdapterになってしまうのだ。

以下はpryの結果。

pry > ActiveJob::Base.queue_adapter => #<ActiveJob::QueueAdapters::TestAdapter:0x00007fa7646755d0 @enqueued_jobs=, @filter=nil, @perform_enqueued_at_jobs=true, @perform_enqueued_jobs=true, @performed_jobs=, @reject=nil>

どれだけconfig/environments/test.rbのほうでqueue_adapterの設定をいじり回そうと、意味がなかったのだが、これにハマってしまっていた…。

とりあえず、コードの修正によってActiveJobが突如動かなくなった理由はまだわかっていないのだが、ActiveJobをテストで動かすときの設定については理解できたのでよかった。

まとめ

  1. キューイングのテストが不要でActiveJobの結果をすぐに反映してテストをしたい場合は、ActiveJob::TestHelperを読み込まずに、config/environments/test.rbでconfig.active_job.queue_adapter = :asyncと読み込めばよい。
  2. ActiveJobのキューイングや実行タイミングを自分で制御したい場合はActiveJob::TestHelperを読み込む。その場合は、config/environments/test.rbでconfig.active_job.queue_adapterを設定しても意味はない。

あとは昔に自分がqiitaに書いていたやつの通りにやれば問題なかった。

qiita.com