A Rails app I'm working on performs some expensive operations that should be offloaded to another process, so I'm using this as an opportunity to try out BackgrounDRb. Because I'm doing BDD with RSpec, my first instinct, after installing and generating a worker, was to write a spec for my worker. However, Googling for the best way to do this turned up nothing, so I'm posting what I did. If you have a better way to do this, I'd love to hear it. If not, I hope this saves someone some time.
First, I created a new directory under my spec directory:
svn mkdir spec/workers
Then, I wrote the following in a file called collecting_worker_spec.rb in the newly-created workers directory (my worker is called CollectingWorker)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
require File.dirname(__FILE__) + '/../spec_helper' describe CollectingWorker, "with feeds needing collection" do before(:each) do @worker = CollectingWorker.new end it "should pull a single feed" do mock_collector = returning mock('collector') do |m| m.should_receive(:collect) end Collector.should_receive(:pop).and_return(mock_collector) @worker.do_work(true) end end |
For this spec to run correctly, though, I needed to add some code to my spec_helper.rb. This isn't pretty, but it is working for me:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
module BackgrounDRb module Worker class RailsBase def self.register; end end end end worker_path = File.dirname(__FILE__) + "/../lib/workers" spec_files = Dir.entries(worker_path).select {|x| /\.rb\z/ =~ x} spec_files -= [ File.basename(__FILE__) ] spec_files.each do |path| require(File.join(worker_path, path)) end |
All of the necessary RailsBase methods get mocked or stubbed in the spec itself. The class declaration is there so the necessary constants can be found when they're needed. There's probably a better place for that declaration, but the fact that so little code is needed for me to begin speccing my workers is a testament to the power of RSpec and its mocking facilities.