Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to test delayed_job callback hooks using RSpec

I'd like to verify that delayed_job callback hooks are getting called, but I don't see how to get RSpec to do it, especially when several layers of classes are involved.

Assuming I have an ActiveRecord model like this:

class MyJob < ActiveRecord::Base
  def perform
    # do some stuff
  end
  def after(job)
    # called by delayed_job after perform completes
  end
end

Conceptually, I want an RSpec test along these lines (though I know this isn't correct):

it 'should call the :after callback hook' do
  my_job = MyJob.create
  my_job.should_receive(:after).with(an_instance_of(Delayed::Backend::ActiveRecord::Job))

  Delayed::Job.enqueue(my_job)
  Delayed::Worker.new.work_off
end

I've pored over stackoverflow, relishapp.com/rspec and all the other places I can think of. It can't be too hard, right? (I bet @zetetic knows the answer in his sleep... ;)

(Caveat: My actual case uses a 'shim' class between MyJob and DJ. An answer for this simple case may trigger a more complex follow-on!)

like image 391
fearless_fool Avatar asked Nov 04 '22 16:11

fearless_fool


2 Answers

IMHO i don't think this is the best thing to do...

By doing this, you're trying to spec DelayedJob's behavior, not your app, and DJ already has its own suit of tests.

Anyway, what about mocking DelayedJob itself? Maybe you can specify, by doing that, that your MockedJob will call your hook after processing, and you can create your matchers/expectations accordingly...

like image 138
Rudy Seidinger Avatar answered Nov 09 '22 11:11

Rudy Seidinger


My suggestion would be to see if the Jobs table creates a new job record, and then introspect the details of that record. I've used something like this in the past.

it "should sync content from the remote CMS" do      
  DelayedJobs::CMS::Sync.module_eval do
  def perform
    url.should == "http://example.com/tools/datafeed/resorts/all"
    Report.sync!([{'id' => 1, 'name' => 'resort foo'}])
  end
end

lambda do
  Report.sync_all!
end.should change(Delayed::Job, :count)

lambda do
  Delayed::Job.work_off
end.should change(Resort, :count).by(2)
end
like image 29
heavysixer Avatar answered Nov 09 '22 11:11

heavysixer