Incorporating Delayed Job in rspec specs

. . .

Update: The preferred way to do this these days is simply: Delayed::Worker.new.work_off

. . .

I wanted to test the results of some Delayed Job enabled methods in my specs. DJ has a nice method Delayed::Job.work_off that does all of the jobs on the queue. Unfortunately, it does them in a separate thread, so if you run it from rspec and there are errors in your jobs, rspec never hears about them. My solution was to write an even simpler, in-thread job runner: (edit: updated to delete the job too, at Damien’s suggestion)

# lib/delayed_job_spec_helper.rb
module DelayedJobSpecHelper
  def work_off
    Delayed::Job.all.each do |job|
      job.payload_object.perform
      job.destroy
    end
  end
end

My spec might look like this:

describe Thingy do
  include DelayedJobSpecHelper
 
  it "should have been worked on if I do something that queues jobs" do
    thing = Thingy.new
    thing.method_that_queues_jobs
    work_off
    thing.should be_worked_on
  end
end

Voila.

Tags: ,

8 Responses to “Incorporating Delayed Job in rspec specs”

  1. Damien Says:

    Hello,

    Thank you. One very small change I’ve made : when the job is executed, delayed job deleted it.
    To have the same behaviour,my work_off method becomes the following :

    module DelayedJobHelper
    def work_off
    Delayed::Job.all.each do |job|
    job.payload_object.perform
    job.destroy
    end
    end
    end

  2. erik Says:

    Hi Damien!

    Ah, that’s a nice addition. I updated my code to do the same.

  3. Nada Says:

    You can also do this to execute all jobs realtime

    # config/initializers/delayed_job_config.rb
    Delayed::Worker.delay_jobs = !Rails.env.test?

    Not sure if it wasn’t available when you wrote this post.

  4. Brett Says:

    Strange, I get an error with the above:

    “/Library/Ruby/Gems/1.8/gems/aws-s3-0.6.2/lib/aws/s3/extensions.rb:206:in `const_missing’: uninitialized constant DelayedJobSpecHelper (NameError)

  5. jc00ke Says:

    Nada’s approach is money. Works flawlessly & no extra method call.

  6. Roman Says:

    Better use job.invoke_job instead of job.payload_object.perform, otherwise no callbacks won’t be triggered (e.g. before, success, after)

  7. Chris Peters Says:

    Exactly what I was looking for to test a delayed job for moving files to S3. For some reason, the other methods mentioned in the comments did not work on my copy of Rails 3.2.7.

  8. qw3r Says:

    Saved my day! Thank you very much!

Leave a Reply