Mock today

In some of my unit tests, I find the need to set today to a different value than the actual today. For example, to test the model method "balance_of_today", which takes no argument, I want to have Date.today be a specific date for the purpose of testing. In other words, I want to do something like this:

mock_today(Date.new(2008, 2, 1)) do     ... test code... end

My implementation for mock_today is:

  def mock_today(date)     $_mock_test_date = date

    Date.class_eval do       class <<self         alias original_today today       end

      def self.today         $_mock_test_date       end     end

    yield

    Date.class_eval do       class <<self         alias today original_today       end     end   end

So my questions are:

1) Is it a good idea to mock Date.today?

2) Can my implementation of mock_today be improved? I'm particularly worried about of the use of global variable, and of class_eval, since I heard class_eval is becoming outdated as Ruby 1.9 is coming out.

I occasionally "timetravel" by overriding Time.now (and Date.today calls Time.now eventually). It goes a little like this

class Time   cattr_accessor :frozen_now   self.frozen_now = nil   class << self     def now_with_freeze       if @@frozen_now         @@frozen_now       else         now_without_freeze      end    end    alias_method_chain :now, :freeze   end end

Then you freeze by doing Time.frozen_now = ... and unfreeze by setting it back to nil. You could easily refactor this to have a block like syntax.

Fred

Or use flexmock:

require 'rubygems' gem :flexmock require 'flexmock/test_unit'

# then in your test

     stopped_clock = Date.new(2008, 2, 1)      flexmock(Date).should_receive(:today).returns(stopped_clock)

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

Thanks, both of these are good suggestions. I will look into them.