This blog post will show you a very simple way on how you can test if your Resque job gets queued in your controller. The purpose is not to test the actual job itself or to test Resque itself but simply how to test if your controller actually enqueues the job.
In the end, I want the following controller method to work and be tested:
class ProjectsController < ApplicationController
def github_notify
@project = Project.find(params[:id])
Resque.enqueue(RailsBuild, @project.id)
render :nothing => true
end
end
Testing the Resque enqueue with Mocha expectations and disabling Turn
You can test the Resque call with Mocha.
However, you should disable the "turn" gem for now which is enabled by default in every Rails 3.1 project. There is something wrong with turn which brakes Mocha's expectations. The issue seems to be fixed in turn 0.8.3, but that has some other gem compatibility issues.
This will cause pretty test output to be disabled for now until you add a work around or the new gems get released. Which is kind of a bummer.
Now, add the following line to your Gemfile test group and run bundle:
gem 'mocha', :require => false
Next, require mocha in your test_helper:
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'mocha'
class ActiveSupport::TestCase
...
Writing the functional test
Write the following test code and see if it fails:
test "post github_notify queues a new build" do
project = FactoryGirl.create(:project)
Resque.stubs(:enqueue)
Resque.expects(:enqueue).with(RailsBuild, project.id).once
post :github_notify, :id => project.id
assert_response :success
end
In this test, I want to see if Resque queues the RailsBuild job and passes the project id as an argument.
Run your test and watch it fail:
1) Failure:
test_post_github_notify_queues_a_new_build(ProjectsControllerTest) [/Users/michiel/Code/flightcontrol/test/functional/projects_controller_test.rb:81]:
not all expectations were satisfied
unsatisfied expectations:
- expected exactly once, not yet invoked: Resque Client connected to redis://127.0.0.1:6379/0.enqueue(RailsBuild, 1)
satisfied expectations:
- allowed any number of times, not yet invoked: Resque Client connected to redis://127.0.0.1:6379/0.enqueue(any_parameters)
Add your Resque job object if you don't have it yet. I don't have it in this case yet since I'm test-driving my design based on a Cucumber feature.
class RailsBuild
@queue = :rails_build
def self.perform(project_id)
end
end
Write the code for the controller method:
def github_notify
@project = Project.find(params[:id])
Resque.enqueue(RailsBuild, @project.id)
render :nothing => true
end
Run the test and watch it pass:
Loaded suite /Users/michiel/.rvm/gems/ruby-1.9.2-p290/gems/rake-0.9.2.2/lib/rake/rake_test_loader
Started
....................
Finished in 2.643193 seconds.