有时间警察我试过
it 'has the correct amount if falls in the prevIoUs month' do t = "25 May".to_datetime Timecop.travel(t) puts DateTime.now expect(@employee.monthly_sales).to eq 150 end
当我运行规范我可以看到放置DateTime.now给2015-05-25T01:00:00 01:00但有相同的放置DateTime.now在我测试输出的方法2015-07-24T08:57: 53 01:00(今天).
我该如何做到这一点?
——————更新——————————- ——————–
我正在将一个before(所有)块中的记录(@employee等)设置成似乎已经导致了这个问题.它只有在Timecop做阻止之后完成设置时才有效.为什么会这样?
解决方法
Timecop模拟Time,Date和DateTime的构造函数.在冻结和返回之间创建的任何实例(或冻结块内)都将被嘲笑.
在冻结或返回后创建的任何实例都不会受到影响,因为Timecop不会混淆现有对象.
从README(我的重点):
A gem providing “time travel” and “time freezing” capabilities,making it dead simple to test time-dependent code. It provides a unified method to mock Time.now,Date.today,and DateTime.now in a single call.
所以在创建要嘲笑的Time对象之前调用Timecop.freeze是至关重要的.如果您在阻止之前冻结了RSpec,则会在对象进行评估之前运行.但是,如果您有一个在您设置主题的前一个块(在您的案例中为@employee),并且在嵌套描述中还有另一个块,那么您的主题已经设置,在冻结时间之前调用了DateTime.new.
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
而不是使用冻结块,您还可以在钩子之前和之后冻结并返回rspec:
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/