I have a couple rake tasks and I want to write specs for them. Yes, I should extract the programming logic from the rake tasks and encapsulate that logic into appropriate class methods. However this doesn't mean that I shouldn't be able to RSpec rake tasks.

I found an older post that got me 90% of the way to what I needed. The problem is that I suspect some sort of static file name caching is going on behind the scenes in rake so using #rake_require in an RSpec context isn't performing the functionality I was expecting. I tried moving between before :all do and before blocks, nesting describe blocks and all sorts of other craziness. I had 3 different specs and the first spec would always pass and the other two would fail; I could freely re-arrange the spec order and always the spec defined first would pass. This was maddening.

Turns out I just had to use load instead of #rake_require.

Here's what my now working spec ended up looking like, for the curious:

#./spec/lib/tasks/rake_tasks_spec.rb  
require 'spec_helper'  
require 'rake'

describe "rake" do  
  before do
    @rake = Rake::Application.new
    Rake.application = @rake
    # previously was trying
    # Rake.application.rake_require "tasks/get_comic"
    load Rails.root + 'lib/tasks/get_comic.rake'
    Rake::Task.define_task(:environment)
  end

  describe "task get_comic" do
    it "should have 'environment' as a prerequisite" do
      @rake['get_comic'].prerequisites.should include("environment")
    end
    it "works when expected input is received" do
      comic = Comic.new {|c| c.comic_id = 12}
      comic.should_receive(:save).and_return(true)

      result = Ilk::Parser::Result.new { |r| r.comic_id = 12 }
      result.should_receive(:to_model).and_return(comic)

      Ilk::Parser.should_receive(:parse).with(Ilk::Constants::COMIC_URL + '12').and_return(result)
      Comic.should_receive(:find_by_comic_id).with(12).and_return(nil)

      @rake['get_comic'].invoke('12')
    end
    it "raises an error when there was a problem parsing" do
      Ilk::Parser.should_receive(:parse).with(Ilk::Constants::COMIC_URL + '12').and_return(nil)
      -> { @rake['get_comic'].invoke('12') }.should raise_error
    end
  end
end