Factory_girl 的 Timecop:工厂未按预期对日期属性进行排序
Timecop with Factory_girl: factory not sequencing date attribute as expected
我正在使用 timecop gem in order to stub out dates. I am also using factory_girl 以便更轻松地为我的规格创建对象。
这是我的工厂:
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
假设今天的实际日期是 09/07/2016。
这是我的规格:
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
在第一行输出中:Timecop 在我调用 Date.today
时按预期工作。它已成功冻结时间和returns冻结的时间。
但是:第二行没有按预期工作。它显然正在使用系统 Date
而不是 Timecop 的冻结 Date
。已排序的 end_date
应按顺序将 +1 年添加到当前冻结日期。因此:我希望这里的 end_date
是 09/30/2011
,而不是 09/30/2017
。
我怎样才能使排序的 end_date
属性从 Timecop 的 Date
而不是系统的 Date
中消失?
问题出在我传递给 sequence
方法的第二个参数上。该参数在初始化时为 static/evaluated。它不是动态的,因此 timecop
没有机会在评估第二个参数之前删除日期。
trait(:sequenced_end_date) {sequence(:end_date, Date.today.year + 1) {|n| Date.new(n, 9, 30) }}
传递给 sequence
方法的第二个参数的 Date.today.year
部分是静态的,并在初始化时求值。它不是动态的,甚至在调用该方法之前就已经对其进行了评估。
我只需要将这些方法更改为以下内容:
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) }}
现在它按预期工作并且returns以下内容:
Today's frozen date thanks to Timecop: 01/01/2010
Sequenced Date: 09/30/2011
块是动态的,因此在块内调用 Date.today.year + n
使 timecop 有机会在执行此块之前先将 Date
存根。
我正在使用 timecop gem in order to stub out dates. I am also using factory_girl 以便更轻松地为我的规格创建对象。
这是我的工厂:
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
假设今天的实际日期是 09/07/2016。
这是我的规格:
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
在第一行输出中:Timecop 在我调用 Date.today
时按预期工作。它已成功冻结时间和returns冻结的时间。
但是:第二行没有按预期工作。它显然正在使用系统 Date
而不是 Timecop 的冻结 Date
。已排序的 end_date
应按顺序将 +1 年添加到当前冻结日期。因此:我希望这里的 end_date
是 09/30/2011
,而不是 09/30/2017
。
我怎样才能使排序的 end_date
属性从 Timecop 的 Date
而不是系统的 Date
中消失?
问题出在我传递给 sequence
方法的第二个参数上。该参数在初始化时为 static/evaluated。它不是动态的,因此 timecop
没有机会在评估第二个参数之前删除日期。
trait(:sequenced_end_date) {sequence(:end_date, Date.today.year + 1) {|n| Date.new(n, 9, 30) }}
传递给 sequence
方法的第二个参数的 Date.today.year
部分是静态的,并在初始化时求值。它不是动态的,甚至在调用该方法之前就已经对其进行了评估。
我只需要将这些方法更改为以下内容:
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) }}
现在它按预期工作并且returns以下内容:
Today's frozen date thanks to Timecop: 01/01/2010
Sequenced Date: 09/30/2011
块是动态的,因此在块内调用 Date.today.year + n
使 timecop 有机会在执行此块之前先将 Date
存根。