如何假冒Time.now?

use*_*962 70 ruby time unit-testing

Time.now在单元测试中设置测试时间敏感方法的最佳方法是什么?

Jam*_*sen 75

我非常喜欢Timecop库.你可以用块形式做时间扭曲(就像时间扭曲一样):

Timecop.travel(6.days.ago) do
  @model = TimeSensitiveMode.new
end
assert @model.times_up!
Run Code Online (Sandbox Code Playgroud)

(是的,你可以嵌套块式时间旅行.)

您还可以进行声明性时间旅行:

class MyTest < Test::Unit::TestCase
  def setup
    Timecop.travel(...)
  end
  def teardown
    Timecop.return
  end
end
Run Code Online (Sandbox Code Playgroud)

在这里为Timecop配一些黄瓜帮手.他们让你做的事情如下:

Given it is currently January 24, 2008
And I go to the new post page
And I fill in "title" with "An old post"
And I fill in "body" with "..."
And I press "Submit"
And we jump in our Delorean and return to the present
When I go to the home page
I should not see "An old post"
Run Code Online (Sandbox Code Playgroud)


Avd*_*vdi 43

我个人更喜欢让时钟可注射,如下所示:

def hello(clock=Time)
  puts "the time is now: #{clock.now}"
end
Run Code Online (Sandbox Code Playgroud)

要么:

class MyClass
  attr_writer :clock

  def initialize
    @clock = Time
  end

  def hello
    puts "the time is now: #{@clock.now}"
  end
end
Run Code Online (Sandbox Code Playgroud)

但是,许多人更喜欢使用模拟/存根库.在RSpec/flexmock中,您可以使用:

Time.stub!(:now).and_return(Time.mktime(1970,1,1))
Run Code Online (Sandbox Code Playgroud)

或者在摩卡:

Time.stubs(:now).returns(Time.mktime(1970,1,1))
Run Code Online (Sandbox Code Playgroud)

  • 虽然我同意以更可测试的方式编写东西的一般想法,但有时候它根本就不实用.而Time.now就是其中一个例子.它可以在系统的很多部分使用,并且一直传递它将是太多的开销. (5认同)

Sta*_*len 14

我正在使用RSpec,我在调用Time.now之前完成了这个:Time.stub!(:now).and_return(2.days.ago).通过这种方式,我可以控制我用于特定测试用例的时间


Iwa*_*aru 11

使用Rspec 3.2,我发现伪造Time.now返回值的唯一简单方法是:

now = Time.parse("1969-07-20 20:17:40")
allow(Time).to receive(:now) { now }
Run Code Online (Sandbox Code Playgroud)

现在Time.now将永远返回阿波罗11登陆月球的日期.

资料来源:https://www.relishapp.com/rspec/rspec-mocks/docs


Bar*_*cat 10

时间扭曲

time-warp是一个可以满足您需求的库.它为您提供了一个花费时间和块的方法,并且块中发生的任何事情都使用伪造的时间.

pretend_now_is(2000,"jan",1,0) do
  Time.now
end
Run Code Online (Sandbox Code Playgroud)


And*_*imm 7

不要忘记,这Time只是一个引用类对象的常量.如果你愿意发出警告,你可以随时做

real_time_class = Time
Time = FakeTimeClass
# run test
Time = real_time_class
Run Code Online (Sandbox Code Playgroud)