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.