Delayed Job not processed in rspec

Jerome picture Jerome · Jul 7, 2010 · Viewed 10.9k times · Source

I am trying to run rspecs for a custom delayed job (GetPage::GetPageJob), but I have a problem.

When I run them, the jobs are well enqueued (that is to say, well inserted in the delayed_jobs table), but they are not processed by the job worker. Indeed, after launching "rake jobs:work RAILS_ENV=test" in a first terminal, and after running the specs in a second terminal, I don't see any output from the job worker in the first terminal.

On the other hand, the jobs are well processed if I enqueue them via "script/console test". So I'm a bit confused.

With both the specs and the script/console, the line I use to enqueue my jobs is :

Delayed::Job.enqueue GetPage::GetPageJob.new("http://cnn.com")

Any idea ?

Answer

fearless_fool picture fearless_fool · Aug 16, 2011

The simplest way to test queued Delayed::Job tasks in RSpec is to run them in real time. Simply add the following line to your RSpec tests:

Delayed::Worker.delay_jobs = false

This will cause your jobs to be processed immediately upon enqueuing, not in a separate thread. This is usually what you want for testing, since it's deterministic.

Two caveats

  • If you are trying to test for timing errors, race conditions, etc, this approach won't help (since the jobs are processed in the same thread as RSpec)

  • The current version of delayed_job (2.1.4) has a minor bug in which the callback hooks (enqueue, before, success, error, failure) don't get called when Delayed::Worker.delay_jobs is set to false.

Two Workarounds

If you need to test the callback hooks I know of two workarounds:

  • Fetch the latest master branch from github. (I haven't tried that because I need a stable version)

  • Instead of setting Delayed::Worker.delay_jobs = false, explicitly call DJ's run mechanism in your test code as follows:

    successes, failures = Delayed::Worker.new.work_off

That will process whatever is in the job queue (again, in the same thread as the RSpec tests) and return two numbers: the # of jobs that succeeded and the # of jobs that failed. I currently use this approach and it does everything I need.