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.
on 2008-11-19 21:21
on 2008-11-19 21:40
On Nov 19, 8:20 pm, Eric LIn <ericlin...@gmail.com> wrote: > My implementation for mock_today is: > $_mock_test_date > 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
on 2008-11-19 21:44
On Nov 19, 2008, at 3:37 PM, Frederick Cheung wrote: >> end >> >> end >> I heard class_eval is becoming outdated as Ruby 1.9 is coming out. > if @@frozen_now > 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
on 2008-11-19 22:00
Thanks, both of these are good suggestions. I will look into them. On Nov 19, 12:43 pm, Rob Biedenharn <R...@AgileConsultingLLC.com>