2016-09-07 5 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일입니다 가정 :

여기 내 공장입니다.

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

최초의 출력 라인에서 :

사양 여기 실행
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 

이 출력됩니다 :

여기 내 사양입니다 내가 Date.today를 호출 할 때 예상대로 타임 캅 작동합니다. 그것은 성공적으로 시간을 고정시키고 그 고정 된 시간을 반환합니다.

그러나 두 번째 줄이 예상대로 작동하지 않습니다. Timecop의 냉동 Date에 반하여 명확하게 Date 시스템을 사용하고 있습니다. 순차 화 된 end_date은 현재 고정 된 날짜에 +1 년을 순차적으로 추가해야합니다. 따라서 09/30/2017이 아니라 이 09/30/2011 일 것으로 예상됩니다.

시퀀스 end_date의 속성이 시스템의 Date이 아닌 Timecop의 Date이되도록하려면 어떻게해야합니까?

답변

2

sequence 메서드에 전달 된 두 번째 인수에서 문제가 발생했습니다. 이 인수는 초기화시 정적/평가됩니다. 동적이 아니기 때문에 timecop은 두 번째 인수가 평가되기 전에 날짜를 빼낼 수있는 기회가 없었습니다. 두번째 인수 Date.today.year 부분이 메소드로 전달 sequence 정적이고 초기에 평가되고 그게

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를 호출, 동적 timecop은이 블록이 실행되기 전에 먼저 Date을 스텁 아웃 할 수 있습니다.

+1

예 - 비슷한 것을 말하려고했습니다. 'Date.today.year'는 런타임시보다 초기화시 평가됩니다. – Anthony

+0

@Anthony가 시정 해 주셔서 감사합니다. 나는 그것을 더 정확하게 바꾸려고합니다. – Neil