I am trying to run rspecs for a custom delayed job (GetPage::GetPageJob), but I have a problem.
When I ru开发者_StackOverflown 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 ?
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.
In the past, I've tried to do an end-to-end test of logic -> delayed-job -> perform job, and it was too many things. I think rather than test that full sweet using RSpec, you could focus on testing each aspect.
So, test that a job gets inserted. Then, have another test that tests what should happen when a job is executed.
Alternatively, mock out the delayed-job, so that when you enqueue a job, it executes it right away.
You'll need to kick off the worker process from inside your tests rather than from another process. Try:
worker = Delayed::Worker.new(:max_priority => nil, :min_priority => nil, :quiet => true)
worker.work_off
I use the config option to run the jobs in real time:
# config/initializers/delayed_job_config.rb
Delayed::Worker.delay_jobs = !Rails.env.test?
精彩评论