【问题标题】:Trouble with Rspec for timestamp in hashes哈希中时间戳的 Rspec 问题
【发布时间】:2018-11-28 09:11:33
【问题描述】:

为了与我们在规范中使用的 hashdata 进行比较

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

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

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

尝试存根 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 以“你好”的形式出现 但右手边仍然带有时间戳

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

【问题讨论】:

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


    【解决方案1】:

    由于您尚未说明如何定义 response_body_jsonPresenter#page,因此我无法真正回答为什么您当前的尝试不起作用。

    但是,我可以说我会使用不同的方法。

    有两种标准的方式来编写这样的测试:

    1. 冻结时间

    假设您使用的是相对最新的 rails 版本,您可以在测试中的某处使用 use 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
    

    【讨论】:

    • 这是我的 rails 版本 5.0.1 尝试添加 freeze_time 得到这个错误 ' undefined method `freeze_time' '
    • NoMethodError: undefined method `freeze_time' for #<:examplegroups::apiv2somecontroller::getindex:0x007f94275d27e0> 你的意思是?冻结
    • 当我尝试第二种方式时 "updatedAt"=>"2018-11-28T15:12:01.408+​​05:30", :updatedAt=>(在 3 of 2018-11-28 15 以内:12:01 +0530) 这就是数据的走向。
    • @Surya freeze_time 添加到 Rails 5.2。正如我在上面写的,你可以使用travel_to(Time.zone.now)——这实际上是一样的,只是稍微笨拙一些。
    • 但是 travel_to 有效。我必须包括 ActiveSupport::Testing::TimeHelpers 谢谢
    【解决方案2】:
    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 的方法是更好的方法。

    【讨论】:

      猜你喜欢
      • 2019-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-13
      • 2013-12-30
      • 1970-01-01
      • 1970-01-01
      • 2021-05-05
      相关资源
      最近更新 更多