I would like to test some resque workers, and the actions that enqueue jobs with these workers. I am using rspec and rails.
Currently I have a model, let's call it Article.rb, that has a before_save method called updates_related_categories that checks if a job with CategoriesSorter needs to be enqueued. If so, it enqueues a job with that worker, with the argument of the category id that the article is related to.
In test, however, these jobs are sent to the same queue as the development server sends jobs to. (i check using the resque server that you can tie into your server at root/redis/overview)
I want to know:
1) How can I send test jobs to a different queue than the development jobs?
If this is possible, any other advice on testing resque is also welcome.
I have seen some related questions that suggest resque-unit and resque-spec but these are pretty undeveloped, and I couldn't get them to a useful working state. Also, I have heard of using Resque.inline but I don't know if that is relevant in this case, as resque isn't called in test specs, it's called from the article model on save of objects created in test.
Sample Code:
Article.rb:
before_save :update_related_categories
def update_related_categories
#some if statements/checks to see if a related category needs updating
Resque.enqueue(CategoriesWorker, [category_id])
end
end
CategoriesSorter:
class CategoriesSorter
@queue=:sorting_queue
def self.perform(ids)
ids.each do |id|
#some code
end
end
end
Specs:
it "should do something" do
@article = #set something to enqueue a job
@article.save
#can i check if a job is enqueued? can i send this job NOT to the development queue but a different one?
end
As I see it, you don't want to test whether enqueueing the job results in perform being called - we trust Resque does what it should. However, you can test that 1. calling update_related_categories enqueues the job. Then you can test, separately, whether 2. a worker calling perform results in the desired behavior.
For testing Resque in general, a combination of resque-spec and simulating a worker can accomplish the above two goals.
For 1, with resque-spec, you can simulate a worker calling the perform method on your class, and then check that it has been enqueued correctly:
describe "Calling update_related_categories " do
before(:each) do
ResqueSpec.reset!
end
it "should enqueue the job" do
Article.update_related_categories
CategoriesSorter.should have_queue_size_of(1)
end
end
For 2, you can create a Job (and specify a separate queue name than your development queue), a Resque::Worker and then assign the Worker to the Job:
def run_worker_simulation
# see Resque::Job api for setting the args you want
Resque::Job.create('test_queue_name', 'class_name', 'type', 'id')
worker = Resque::Worker.new('test_queue_name')
worker.very_verbose = true
job = worker.reserve
worker.perform(job)
end
Hope that gives you some ideas.