TL; DR:问题是在规范中DateTime.now
调用Employee
之前调用过。Timecop.freeze
Timecop 模拟Time
,Date
和的构造函数DateTime
。freeze
在and之间return
(或在块内)创建的任何实例freeze
都将被模拟。之前或之后
创建的任何实例都不会受到影响,因为 Timecop 不会与现有对象混淆。freeze
return
从自述文件(我的重点):
一个提供“时间旅行”和“时间冻结”功能的 gem,使得测试时间相关代码变得非常简单。它提供了一个统一的方法来在一次调用中模拟 Time.now、Date.today 和 DateTime.now。
因此,在创建要模拟Timecop.freeze
的对象之前调用是必不可少的。Time
如果您freeze
在 RSpecbefore
块中,这将在subject
评估之前运行。但是,如果您有一个before
设置主题的块(在您的情况下),并且在嵌套中@employee
有另一个块,那么您的主题已经设置,在您冻结时间之前已经调用。before
describe
DateTime.new
如果您将以下内容添加到您的Employee
class Employee
def now
DateTime.now
end
end
然后运行以下规范:
describe '#now' do
let(:employee) { @employee }
it 'has the correct amount if falls in the previous month', focus: true do
t = "25 May".to_datetime
Timecop.freeze(t) do
expect(DateTime.now).to eq t
expect(employee.now).to eq t
expect(employee.now.class).to be DateTime
expect(employee.now.class.object_id).to be DateTime.object_id
end
end
end
除了使用freeze
块之外,您还可以在rspecfreeze
和钩子中使用:return
before
after
describe Employee do
let(:frozen_time) { "25 May".to_datetime }
before { Timecop.freeze(frozen_time) }
after { Timecop.return }
subject { FactoryGirl.create :employee }
it 'has the correct amount if falls in the previous month' do
# spec here
end
end
题外话,但也许看看http://betterspecs.org/