与Rspec麻烦的哈希时间戳

时间:2018-11-28 09:11:34

标签: ruby-on-rails ruby rspec rspec-rails

为了与哈希数据进行比较,我们在规范中对此进行了

it 'should return the rec_1 in page format' do
     expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end

Presenter是一个将接受ActiveRecordObject并使用特定格式的哈希数据进行响应的类。

然后我们将带有时间戳的update_at添加到hash_data中。 在我的代码中,我有updated_at = Time.zone.now 因此规格开始失败,因为两个updatedat之间的时间差只有几秒钟。

尝试存根Time.zone

it 'should return the rec_1 in page format' do
     allow(Time.zone).to receive(:now).and_return('hello')
     expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end

,但现在response_body_json.updated_at为'hello' 但右侧仍然带有时间戳

我要去哪里错了??? 还是有其他更好的方法来处理这种情况?

2 个答案:

答案 0 :(得分:3)

由于您尚未显示response_body_jsonPresenter#page的定义方式,因此我无法真正回答您当前的尝试为何无效的情况。

但是,我可以说我会使用另一种方法。

有两种编写测试的标准方法:

  1. 冻结时间

假设您使用的是相对最新的Rails版本,则可以在测试中的某个地方使用ActiveSupport::Testing::TimeHelpers#freeze_time,例如像这样:

around do |example|
  freeze_time { example.run }
end

it 'should return the movie_1 in page format' do
  expect(response_body_json).to eql(Presenter.new(ActiveRecordObject).page)
end

如果您使用的是较旧版本的Rails,则可能需要使用travel_to(Time.zone.now)

如果您使用的是非常旧的Rails版本(或非Rails项目!),但没有此帮助程序库,则可以改用timecop

  1. 使用模糊匹配器作为时间戳记(例如be_within)。类似于以下内容:

it 'should return the movie_1 in page format' do
  expected_json = Presenter.new(ActiveRecordObject).page
  expect(response_body_json).to match(
    expected_json.merge(updated_at: be_within(3.seconds).of(Time.zone.now))
  )
end

答案 1 :(得分:1)

before do
  movie_1.publish
  allow(Time.zone).to receive(:now).and_return(Time.now)
  get :show, format: :json, params: { id: movie_1.uuid }
end

it 'should return the rec_1 in page format' do
 expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end

结束

以上代码解决了我的问题。

好像我在错误的位置给出了此allow(Time.zone).to receive(:now).and_return('hello')。应该将其放置在before块中,以便在测试用例运行之前对其进行设置,而且我猜也可能必须在get请求之前对其进行设置。

但是汤姆·洛德(Tom Lord)的方法是更好的方法。