Forum: Ruby on Rails Mock today

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
7af933f3ac54d39246535542c1cd3fe8?d=identicon&s=25 Eric LIn (Guest)
on 2008-11-19 21:21
(Received via mailing list)
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.
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2008-11-19 21:40
(Received via mailing list)
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
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2008-11-19 21:44
(Received via mailing list)
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
7af933f3ac54d39246535542c1cd3fe8?d=identicon&s=25 Eric LIn (Guest)
on 2008-11-19 22:00
(Received via mailing list)
Thanks, both of these are good suggestions.  I will look into them.

On Nov 19, 12:43 pm, Rob Biedenharn <R...@AgileConsultingLLC.com>
This topic is locked and can not be replied to.