2016-09-07 7 views
2

日付をスタブアウトするためにtimecopの宝石を使用しています。私はまた、factory_girlを使用して、仕様のオブジェクトを簡単に作成しています。ここでFactory_girlを使用したTimecop:日付の属性がシーケンスされていない可能性があります。

は私の工場で:

FactoryGirl.define do 
    factory :fiscal_year do 
    start_date {Date.today} 
    end_date {Date.today + 1.day} 

    trait(:sequenced_start_date) {sequence(:start_date, Date.today.year) {|n| Date.new(n, 10, 1) }} 
    trait(:sequenced_end_date) {sequence(:end_date, Date.today.year + 1) {|n| Date.new(n, 9, 30) }} 


    factory :sequenced_fiscal_year, parent: :fiscal_year, 
      traits: [:sequenced_start_date, :sequenced_end_date] 
    end 
end 

は、今日の実際日は2016年9月7日であると仮定します。ここで

は私のスペックです:

RSpec.describe FiscalYear, type: :model do 
    before(:example) do 
    Timecop.freeze(Time.local(2010)) 
    end 
    after do 
    Timecop.return 
    end 

    describe "fake spec to show unexpected sequence behavior" do 
    it "tests something" do 
     puts "Today's frozen date thanks to Timecop: #{Date.today}" 
     fiscal_year = create(:sequenced_fiscal_year) 
     puts "Sequenced Date: #{fiscal_year.end_date}" 
    end 
    end 
end 

スペックが、ここで実行されると出力されます:最初の出力ラインで

Today's frozen date thanks to Timecop: 01/01/2010 
Sequenced Date: 09/30/2017 

:私はDate.todayを呼び出すときTimecopは期待通りに動作します。それは時間を凍結させ、その凍った時間を返します。

ただし、2行目が期待どおりに動作しません。 TimecopのフリーズしたDateとは対照的に、システムDateを使用していることは明らかです。シーケンス番号end_dateは、現在凍結された日付に+1年を順次追加する必要があります。したがって、09/30/2017ではなくが09/30/2011であると私は期待しています。

シーケンスend_dateの属性が、システムのDateではなく、TimecopのDateになるようにするにはどうすればよいですか?

答えて

2

私がsequenceメソッドに渡していた2番目の引数で問題が発生しました。この引数は初期化時に静的/評価されます。動的ではないので、timecopは、2番目の引数が評価される前に日付をスタブする機会がありませんでした。 sequenceメソッドに渡される第二引数のDate.today.year一部が静的および初期化時に評価されること

trait(:sequenced_end_date) {sequence(:end_date, Date.today.year + 1) {|n| Date.new(n, 9, 30) }} 

。これは動的ではなく、メソッドが呼び出される前にすでに評価されています。

私は単純に次のようにこれらのメソッドを変更するために必要な:

trait(:sequenced_year_start_date) {sequence(:start_date) {|n| Date.new(Date.today.year, 10, 1) }} 
trait(:sequenced_year_end_date) {sequence(:end_date) {|n| Date.new(Date.today.year + n, 9, 30) }} 

今では期待通りに動作し、次の値を返します。

Today's frozen date thanks to Timecop: 01/01/2010 
Sequenced Date: 09/30/2011 

ブロックは動的であるので、ブロック内Date.today.year + nを呼び出すとなりますこのブロックが実行される前に、最初にスタンプするDateのタイムキャップを設定します。

+1

yep - ちょうど同様のことを言うつもりだった。 'Date.today.year'は初期化時に問題となる実行時よりも評価されます。 – Anthony

+0

@Anthonyは訂正してくれてありがとう。私はそれをより正確に変更します。 – Neil

関連する問題