Railsテスト時に日付を固定にする方法 (for Test::Unit)  [ruby]  [rails]  [TDD]

Railsで試験をする時に、日付に依存する機能(次の誕生日までの日数を求めるとか。。)がある時、今までならfixtureに

date: <%= Date.today().to_s %>

とか、動的にfixtureを定義していたのですが、いろいろロジックが複雑になりだしたので、発想を逆にすることにしました。

つまり、テストの日付を固定するという方法です。

基本的に、Date.today()や、Time.now()を上書きしてやるのですが、他のテストに影響を与えないようにやる必要があります。

そこで、Test::Unit::TestCaseのsetup/teardown内で、関数の再定義、もとの定義への戻しをやってやります。

hoge_controller_test.rb

:
#このテストは2008年9月で試験
class Date
  def self.fixed_today
    return Date.new(2008,9,1)
  end
end

class HogeControllerTest < Test::Unit::TestCase 
  def setup
    Date.instance_eval do
      alias :orig_today :today
      alias :today :fixed_today
    end
  end
  def teardown
    Date.instance_eval do
      alias :fixed_today :today
      alias :today :orig_today
    end
  end
:
end

特異メソッドのaliasを作成するので、instance_evalを利用してaliasによる関数の入れ替えをしています。